184865Sobrien/* POWER/PowerPC XCOFF linker support.
2218822Sdim   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3218822Sdim   2005, 2006, 2007 Free Software Foundation, Inc.
484865Sobrien   Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
584865Sobrien
6104834Sobrien   This file is part of BFD, the Binary File Descriptor library.
784865Sobrien
8104834Sobrien   This program is free software; you can redistribute it and/or modify
9104834Sobrien   it under the terms of the GNU General Public License as published by
10104834Sobrien   the Free Software Foundation; either version 2 of the License, or
11104834Sobrien   (at your option) any later version.
1284865Sobrien
13104834Sobrien   This program is distributed in the hope that it will be useful,
14104834Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
15104834Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16104834Sobrien   GNU General Public License for more details.
1784865Sobrien
18104834Sobrien   You should have received a copy of the GNU General Public License
19104834Sobrien   along with this program; if not, write to the Free Software
20218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2184865Sobrien
22218822Sdim#include "sysdep.h"
2384865Sobrien#include "bfd.h"
2484865Sobrien#include "bfdlink.h"
2584865Sobrien#include "libbfd.h"
2684865Sobrien#include "coff/internal.h"
2794536Sobrien#include "coff/xcoff.h"
2884865Sobrien#include "libcoff.h"
2994536Sobrien#include "libxcoff.h"
3084865Sobrien
3184865Sobrien/* This file holds the XCOFF linker code.  */
3284865Sobrien
33218822Sdim#undef  STRING_SIZE_SIZE
34218822Sdim#define STRING_SIZE_SIZE 4
3584865Sobrien
3684865Sobrien/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
3784865Sobrien   This flag will only be used on input sections.  */
3884865Sobrien
3984865Sobrien#define SEC_MARK (SEC_ROM)
4084865Sobrien
4184865Sobrien/* The list of import files.  */
4284865Sobrien
4394536Sobrienstruct xcoff_import_file
4494536Sobrien{
4584865Sobrien  /* The next entry in the list.  */
4684865Sobrien  struct xcoff_import_file *next;
4784865Sobrien  /* The path.  */
4884865Sobrien  const char *path;
4984865Sobrien  /* The file name.  */
5084865Sobrien  const char *file;
5184865Sobrien  /* The member name.  */
5284865Sobrien  const char *member;
5384865Sobrien};
5484865Sobrien
5584865Sobrien/* Information we keep for each section in the output file during the
5684865Sobrien   final link phase.  */
5784865Sobrien
5894536Sobrienstruct xcoff_link_section_info
5994536Sobrien{
6084865Sobrien  /* The relocs to be output.  */
6184865Sobrien  struct internal_reloc *relocs;
6284865Sobrien  /* For each reloc against a global symbol whose index was not known
6384865Sobrien     when the reloc was handled, the global hash table entry.  */
6484865Sobrien  struct xcoff_link_hash_entry **rel_hashes;
6584865Sobrien  /* If there is a TOC relative reloc against a global symbol, and the
6684865Sobrien     index of the TOC symbol is not known when the reloc was handled,
6784865Sobrien     an entry is added to this linked list.  This is not an array,
6884865Sobrien     like rel_hashes, because this case is quite uncommon.  */
69218822Sdim  struct xcoff_toc_rel_hash
70218822Sdim  {
7184865Sobrien    struct xcoff_toc_rel_hash *next;
7284865Sobrien    struct xcoff_link_hash_entry *h;
7384865Sobrien    struct internal_reloc *rel;
7484865Sobrien  } *toc_rel_hashes;
7584865Sobrien};
7684865Sobrien
7784865Sobrien/* Information that we pass around while doing the final link step.  */
7884865Sobrien
7994536Sobrienstruct xcoff_final_link_info
8094536Sobrien{
8184865Sobrien  /* General link information.  */
8284865Sobrien  struct bfd_link_info *info;
8384865Sobrien  /* Output BFD.  */
8484865Sobrien  bfd *output_bfd;
8584865Sobrien  /* Hash table for long symbol names.  */
8684865Sobrien  struct bfd_strtab_hash *strtab;
8784865Sobrien  /* Array of information kept for each output section, indexed by the
8884865Sobrien     target_index field.  */
8984865Sobrien  struct xcoff_link_section_info *section_info;
9084865Sobrien  /* Symbol index of last C_FILE symbol (-1 if none).  */
9184865Sobrien  long last_file_index;
9284865Sobrien  /* Contents of last C_FILE symbol.  */
9384865Sobrien  struct internal_syment last_file;
9484865Sobrien  /* Symbol index of TOC symbol.  */
9584865Sobrien  long toc_symindx;
9684865Sobrien  /* Start of .loader symbols.  */
9794536Sobrien  bfd_byte *ldsym;
9884865Sobrien  /* Next .loader reloc to swap out.  */
9994536Sobrien  bfd_byte *ldrel;
10084865Sobrien  /* File position of start of line numbers.  */
10184865Sobrien  file_ptr line_filepos;
10284865Sobrien  /* Buffer large enough to hold swapped symbols of any input file.  */
10384865Sobrien  struct internal_syment *internal_syms;
10484865Sobrien  /* Buffer large enough to hold output indices of symbols of any
10584865Sobrien     input file.  */
10684865Sobrien  long *sym_indices;
10784865Sobrien  /* Buffer large enough to hold output symbols for any input file.  */
10884865Sobrien  bfd_byte *outsyms;
10984865Sobrien  /* Buffer large enough to hold external line numbers for any input
11084865Sobrien     section.  */
11184865Sobrien  bfd_byte *linenos;
11284865Sobrien  /* Buffer large enough to hold any input section.  */
11384865Sobrien  bfd_byte *contents;
11484865Sobrien  /* Buffer large enough to hold external relocs of any input section.  */
11584865Sobrien  bfd_byte *external_relocs;
11684865Sobrien};
11784865Sobrien
118218822Sdimstatic bfd_boolean xcoff_mark (struct bfd_link_info *, asection *);
119218822Sdim
12084865Sobrien
12184865Sobrien
12284865Sobrien/* Routines to read XCOFF dynamic information.  This don't really
12384865Sobrien   belong here, but we already have the ldsym manipulation routines
12484865Sobrien   here.  */
12584865Sobrien
12684865Sobrien/* Read the contents of a section.  */
12784865Sobrien
128130561Sobrienstatic bfd_boolean
129218822Sdimxcoff_get_section_contents (bfd *abfd, asection *sec)
13084865Sobrien{
13184865Sobrien  if (coff_section_data (abfd, sec) == NULL)
13284865Sobrien    {
13394536Sobrien      bfd_size_type amt = sizeof (struct coff_section_tdata);
134218822Sdim
13594536Sobrien      sec->used_by_bfd = bfd_zalloc (abfd, amt);
13684865Sobrien      if (sec->used_by_bfd == NULL)
137130561Sobrien	return FALSE;
13884865Sobrien    }
13984865Sobrien
14084865Sobrien  if (coff_section_data (abfd, sec)->contents == NULL)
14184865Sobrien    {
142218822Sdim      bfd_byte *contents;
14384865Sobrien
144218822Sdim      if (! bfd_malloc_and_get_section (abfd, sec, &contents))
145218822Sdim	{
146218822Sdim	  if (contents != NULL)
147218822Sdim	    free (contents);
148218822Sdim	  return FALSE;
149218822Sdim	}
150218822Sdim      coff_section_data (abfd, sec)->contents = contents;
15184865Sobrien    }
15284865Sobrien
153130561Sobrien  return TRUE;
15484865Sobrien}
15584865Sobrien
15684865Sobrien/* Get the size required to hold the dynamic symbols.  */
15784865Sobrien
15884865Sobrienlong
159218822Sdim_bfd_xcoff_get_dynamic_symtab_upper_bound (bfd *abfd)
16084865Sobrien{
16184865Sobrien  asection *lsec;
16284865Sobrien  bfd_byte *contents;
16384865Sobrien  struct internal_ldhdr ldhdr;
16484865Sobrien
16584865Sobrien  if ((abfd->flags & DYNAMIC) == 0)
16684865Sobrien    {
16784865Sobrien      bfd_set_error (bfd_error_invalid_operation);
16884865Sobrien      return -1;
16984865Sobrien    }
17084865Sobrien
17184865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
17284865Sobrien  if (lsec == NULL)
17384865Sobrien    {
17484865Sobrien      bfd_set_error (bfd_error_no_symbols);
17584865Sobrien      return -1;
17684865Sobrien    }
17784865Sobrien
17884865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
17984865Sobrien    return -1;
18084865Sobrien  contents = coff_section_data (abfd, lsec)->contents;
18184865Sobrien
182218822Sdim  bfd_xcoff_swap_ldhdr_in (abfd, (void *) contents, &ldhdr);
18384865Sobrien
18484865Sobrien  return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
18584865Sobrien}
18684865Sobrien
18784865Sobrien/* Get the dynamic symbols.  */
18884865Sobrien
18984865Sobrienlong
190218822Sdim_bfd_xcoff_canonicalize_dynamic_symtab (bfd *abfd, asymbol **psyms)
19184865Sobrien{
19284865Sobrien  asection *lsec;
19384865Sobrien  bfd_byte *contents;
19484865Sobrien  struct internal_ldhdr ldhdr;
19584865Sobrien  const char *strings;
19694536Sobrien  bfd_byte *elsym, *elsymend;
19784865Sobrien  coff_symbol_type *symbuf;
19884865Sobrien
19984865Sobrien  if ((abfd->flags & DYNAMIC) == 0)
20084865Sobrien    {
20184865Sobrien      bfd_set_error (bfd_error_invalid_operation);
20284865Sobrien      return -1;
20384865Sobrien    }
20484865Sobrien
20584865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
20684865Sobrien  if (lsec == NULL)
20784865Sobrien    {
20884865Sobrien      bfd_set_error (bfd_error_no_symbols);
20984865Sobrien      return -1;
21084865Sobrien    }
21184865Sobrien
21284865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
21384865Sobrien    return -1;
21484865Sobrien  contents = coff_section_data (abfd, lsec)->contents;
21584865Sobrien
216130561Sobrien  coff_section_data (abfd, lsec)->keep_contents = TRUE;
21784865Sobrien
21894536Sobrien  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
21984865Sobrien
22084865Sobrien  strings = (char *) contents + ldhdr.l_stoff;
22184865Sobrien
222218822Sdim  symbuf = bfd_zalloc (abfd, ldhdr.l_nsyms * sizeof (* symbuf));
22384865Sobrien  if (symbuf == NULL)
22484865Sobrien    return -1;
22584865Sobrien
22694536Sobrien  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
22794536Sobrien
22894536Sobrien  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
22994536Sobrien  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd), symbuf++, psyms++)
23084865Sobrien    {
23184865Sobrien      struct internal_ldsym ldsym;
23284865Sobrien
23394536Sobrien      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
23484865Sobrien
23584865Sobrien      symbuf->symbol.the_bfd = abfd;
23684865Sobrien
23784865Sobrien      if (ldsym._l._l_l._l_zeroes == 0)
23884865Sobrien	symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
23984865Sobrien      else
24084865Sobrien	{
24194536Sobrien	  char *c;
24284865Sobrien
24394536Sobrien	  c = bfd_alloc (abfd, (bfd_size_type) SYMNMLEN + 1);
24494536Sobrien	  if (c == NULL)
24594536Sobrien	    return -1;
24694536Sobrien	  memcpy (c, ldsym._l._l_name, SYMNMLEN);
24794536Sobrien	  c[SYMNMLEN] = '\0';
24894536Sobrien	  symbuf->symbol.name = c;
24984865Sobrien	}
25084865Sobrien
25184865Sobrien      if (ldsym.l_smclas == XMC_XO)
25284865Sobrien	symbuf->symbol.section = bfd_abs_section_ptr;
25384865Sobrien      else
25484865Sobrien	symbuf->symbol.section = coff_section_from_bfd_index (abfd,
25584865Sobrien							      ldsym.l_scnum);
25684865Sobrien      symbuf->symbol.value = ldsym.l_value - symbuf->symbol.section->vma;
25784865Sobrien
25884865Sobrien      symbuf->symbol.flags = BSF_NO_FLAGS;
25984865Sobrien      if ((ldsym.l_smtype & L_EXPORT) != 0)
26084865Sobrien	symbuf->symbol.flags |= BSF_GLOBAL;
26184865Sobrien
26284865Sobrien      /* FIXME: We have no way to record the other information stored
263130561Sobrien	 with the loader symbol.  */
26484865Sobrien      *psyms = (asymbol *) symbuf;
26584865Sobrien    }
26684865Sobrien
26784865Sobrien  *psyms = NULL;
26884865Sobrien
26984865Sobrien  return ldhdr.l_nsyms;
27084865Sobrien}
27184865Sobrien
27284865Sobrien/* Get the size required to hold the dynamic relocs.  */
27384865Sobrien
27484865Sobrienlong
275218822Sdim_bfd_xcoff_get_dynamic_reloc_upper_bound (bfd *abfd)
27684865Sobrien{
27784865Sobrien  asection *lsec;
27884865Sobrien  bfd_byte *contents;
27984865Sobrien  struct internal_ldhdr ldhdr;
28084865Sobrien
28184865Sobrien  if ((abfd->flags & DYNAMIC) == 0)
28284865Sobrien    {
28384865Sobrien      bfd_set_error (bfd_error_invalid_operation);
28484865Sobrien      return -1;
28584865Sobrien    }
28684865Sobrien
28784865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
28884865Sobrien  if (lsec == NULL)
28984865Sobrien    {
29084865Sobrien      bfd_set_error (bfd_error_no_symbols);
29184865Sobrien      return -1;
29284865Sobrien    }
29384865Sobrien
29484865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
29584865Sobrien    return -1;
29684865Sobrien  contents = coff_section_data (abfd, lsec)->contents;
29784865Sobrien
29894536Sobrien  bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
29984865Sobrien
30084865Sobrien  return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
30184865Sobrien}
30284865Sobrien
30384865Sobrien/* Get the dynamic relocs.  */
30484865Sobrien
30584865Sobrienlong
306218822Sdim_bfd_xcoff_canonicalize_dynamic_reloc (bfd *abfd,
307218822Sdim				       arelent **prelocs,
308218822Sdim				       asymbol **syms)
30984865Sobrien{
31084865Sobrien  asection *lsec;
31184865Sobrien  bfd_byte *contents;
31284865Sobrien  struct internal_ldhdr ldhdr;
31384865Sobrien  arelent *relbuf;
31494536Sobrien  bfd_byte *elrel, *elrelend;
31584865Sobrien
31684865Sobrien  if ((abfd->flags & DYNAMIC) == 0)
31784865Sobrien    {
31884865Sobrien      bfd_set_error (bfd_error_invalid_operation);
31984865Sobrien      return -1;
32084865Sobrien    }
32184865Sobrien
32284865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
32384865Sobrien  if (lsec == NULL)
32484865Sobrien    {
32584865Sobrien      bfd_set_error (bfd_error_no_symbols);
32684865Sobrien      return -1;
32784865Sobrien    }
32884865Sobrien
32984865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
33084865Sobrien    return -1;
33184865Sobrien  contents = coff_section_data (abfd, lsec)->contents;
33284865Sobrien
33394536Sobrien  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
33484865Sobrien
335218822Sdim  relbuf = bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent));
33684865Sobrien  if (relbuf == NULL)
33784865Sobrien    return -1;
33884865Sobrien
33994536Sobrien  elrel = contents + bfd_xcoff_loader_reloc_offset(abfd, &ldhdr);
34094536Sobrien
34194536Sobrien  elrelend = elrel + ldhdr.l_nreloc * bfd_xcoff_ldrelsz(abfd);
34294536Sobrien  for (; elrel < elrelend; elrel += bfd_xcoff_ldrelsz(abfd), relbuf++,
34394536Sobrien	 prelocs++)
34484865Sobrien    {
34584865Sobrien      struct internal_ldrel ldrel;
34684865Sobrien
34794536Sobrien      bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
34884865Sobrien
34984865Sobrien      if (ldrel.l_symndx >= 3)
35084865Sobrien	relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
35184865Sobrien      else
35284865Sobrien	{
35384865Sobrien	  const char *name;
35484865Sobrien	  asection *sec;
35584865Sobrien
35684865Sobrien	  switch (ldrel.l_symndx)
35784865Sobrien	    {
35884865Sobrien	    case 0:
35984865Sobrien	      name = ".text";
36084865Sobrien	      break;
36184865Sobrien	    case 1:
36284865Sobrien	      name = ".data";
36384865Sobrien	      break;
36484865Sobrien	    case 2:
36584865Sobrien	      name = ".bss";
36684865Sobrien	      break;
36784865Sobrien	    default:
36884865Sobrien	      abort ();
36984865Sobrien	      break;
37084865Sobrien	    }
37184865Sobrien
37284865Sobrien	  sec = bfd_get_section_by_name (abfd, name);
37384865Sobrien	  if (sec == NULL)
37484865Sobrien	    {
37584865Sobrien	      bfd_set_error (bfd_error_bad_value);
37684865Sobrien	      return -1;
37784865Sobrien	    }
37884865Sobrien
37984865Sobrien	  relbuf->sym_ptr_ptr = sec->symbol_ptr_ptr;
38084865Sobrien	}
38184865Sobrien
38284865Sobrien      relbuf->address = ldrel.l_vaddr;
38384865Sobrien      relbuf->addend = 0;
38484865Sobrien
38584865Sobrien      /* Most dynamic relocs have the same type.  FIXME: This is only
386130561Sobrien	 correct if ldrel.l_rtype == 0.  In other cases, we should use
387130561Sobrien	 a different howto.  */
38894536Sobrien      relbuf->howto = bfd_xcoff_dynamic_reloc_howto(abfd);
38984865Sobrien
39084865Sobrien      /* FIXME: We have no way to record the l_rsecnm field.  */
39184865Sobrien
39284865Sobrien      *prelocs = relbuf;
39384865Sobrien    }
39484865Sobrien
39584865Sobrien  *prelocs = NULL;
39684865Sobrien
39784865Sobrien  return ldhdr.l_nreloc;
39884865Sobrien}
39984865Sobrien
40084865Sobrien/* Routine to create an entry in an XCOFF link hash table.  */
40184865Sobrien
40284865Sobrienstatic struct bfd_hash_entry *
403218822Sdimxcoff_link_hash_newfunc (struct bfd_hash_entry *entry,
404218822Sdim			 struct bfd_hash_table *table,
405218822Sdim			 const char *string)
40684865Sobrien{
40784865Sobrien  struct xcoff_link_hash_entry *ret = (struct xcoff_link_hash_entry *) entry;
40884865Sobrien
40984865Sobrien  /* Allocate the structure if it has not already been allocated by a
41084865Sobrien     subclass.  */
411218822Sdim  if (ret == NULL)
412218822Sdim    ret = bfd_hash_allocate (table, sizeof (* ret));
413218822Sdim  if (ret == NULL)
414218822Sdim    return NULL;
41584865Sobrien
41684865Sobrien  /* Call the allocation method of the superclass.  */
41784865Sobrien  ret = ((struct xcoff_link_hash_entry *)
41884865Sobrien	 _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
41984865Sobrien				 table, string));
42084865Sobrien  if (ret != NULL)
42184865Sobrien    {
42284865Sobrien      /* Set local fields.  */
42384865Sobrien      ret->indx = -1;
42484865Sobrien      ret->toc_section = NULL;
42584865Sobrien      ret->u.toc_indx = -1;
42684865Sobrien      ret->descriptor = NULL;
42784865Sobrien      ret->ldsym = NULL;
42884865Sobrien      ret->ldindx = -1;
42984865Sobrien      ret->flags = 0;
43084865Sobrien      ret->smclas = XMC_UA;
43184865Sobrien    }
43284865Sobrien
43384865Sobrien  return (struct bfd_hash_entry *) ret;
43484865Sobrien}
43584865Sobrien
43684865Sobrien/* Create a XCOFF link hash table.  */
43784865Sobrien
43884865Sobrienstruct bfd_link_hash_table *
439218822Sdim_bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
44084865Sobrien{
44184865Sobrien  struct xcoff_link_hash_table *ret;
442218822Sdim  bfd_size_type amt = sizeof (* ret);
44384865Sobrien
444218822Sdim  ret = bfd_malloc (amt);
445218822Sdim  if (ret == NULL)
446218822Sdim    return NULL;
447218822Sdim  if (!_bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc,
448218822Sdim				  sizeof (struct xcoff_link_hash_entry)))
44984865Sobrien    {
450104834Sobrien      free (ret);
451218822Sdim      return NULL;
45284865Sobrien    }
45384865Sobrien
45484865Sobrien  ret->debug_strtab = _bfd_xcoff_stringtab_init ();
45584865Sobrien  ret->debug_section = NULL;
45684865Sobrien  ret->loader_section = NULL;
45784865Sobrien  ret->ldrel_count = 0;
45884865Sobrien  memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr));
45984865Sobrien  ret->linkage_section = NULL;
46084865Sobrien  ret->toc_section = NULL;
46184865Sobrien  ret->descriptor_section = NULL;
46284865Sobrien  ret->imports = NULL;
46384865Sobrien  ret->file_align = 0;
464130561Sobrien  ret->textro = FALSE;
465130561Sobrien  ret->gc = FALSE;
46684865Sobrien  memset (ret->special_sections, 0, sizeof ret->special_sections);
46784865Sobrien
46884865Sobrien  /* The linker will always generate a full a.out header.  We need to
46984865Sobrien     record that fact now, before the sizeof_headers routine could be
47084865Sobrien     called.  */
471130561Sobrien  xcoff_data (abfd)->full_aouthdr = TRUE;
47284865Sobrien
47384865Sobrien  return &ret->root;
47484865Sobrien}
47584865Sobrien
476104834Sobrien/* Free a XCOFF link hash table.  */
477104834Sobrien
478104834Sobrienvoid
479218822Sdim_bfd_xcoff_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
480104834Sobrien{
481104834Sobrien  struct xcoff_link_hash_table *ret = (struct xcoff_link_hash_table *) hash;
482104834Sobrien
483104834Sobrien  _bfd_stringtab_free (ret->debug_strtab);
484104834Sobrien  bfd_hash_table_free (&ret->root.table);
485104834Sobrien  free (ret);
486104834Sobrien}
48784865Sobrien
48884865Sobrien/* Read internal relocs for an XCOFF csect.  This is a wrapper around
48984865Sobrien   _bfd_coff_read_internal_relocs which tries to take advantage of any
49084865Sobrien   relocs which may have been cached for the enclosing section.  */
49184865Sobrien
49284865Sobrienstatic struct internal_reloc *
493218822Sdimxcoff_read_internal_relocs (bfd *abfd,
494218822Sdim			    asection *sec,
495218822Sdim			    bfd_boolean cache,
496218822Sdim			    bfd_byte *external_relocs,
497218822Sdim			    bfd_boolean require_internal,
498218822Sdim			    struct internal_reloc *internal_relocs)
49984865Sobrien{
50084865Sobrien  if (coff_section_data (abfd, sec) != NULL
50184865Sobrien      && coff_section_data (abfd, sec)->relocs == NULL
50284865Sobrien      && xcoff_section_data (abfd, sec) != NULL)
50384865Sobrien    {
50484865Sobrien      asection *enclosing;
50584865Sobrien
50684865Sobrien      enclosing = xcoff_section_data (abfd, sec)->enclosing;
50784865Sobrien
50884865Sobrien      if (enclosing != NULL
50984865Sobrien	  && (coff_section_data (abfd, enclosing) == NULL
51084865Sobrien	      || coff_section_data (abfd, enclosing)->relocs == NULL)
51184865Sobrien	  && cache
51284865Sobrien	  && enclosing->reloc_count > 0)
51384865Sobrien	{
514130561Sobrien	  if (_bfd_coff_read_internal_relocs (abfd, enclosing, TRUE,
515218822Sdim					      external_relocs, FALSE, NULL)
51684865Sobrien	      == NULL)
51784865Sobrien	    return NULL;
51884865Sobrien	}
51984865Sobrien
52084865Sobrien      if (enclosing != NULL
52184865Sobrien	  && coff_section_data (abfd, enclosing) != NULL
52284865Sobrien	  && coff_section_data (abfd, enclosing)->relocs != NULL)
52384865Sobrien	{
52484865Sobrien	  size_t off;
52584865Sobrien
52684865Sobrien	  off = ((sec->rel_filepos - enclosing->rel_filepos)
52784865Sobrien		 / bfd_coff_relsz (abfd));
52894536Sobrien
52984865Sobrien	  if (! require_internal)
53084865Sobrien	    return coff_section_data (abfd, enclosing)->relocs + off;
53184865Sobrien	  memcpy (internal_relocs,
53284865Sobrien		  coff_section_data (abfd, enclosing)->relocs + off,
53384865Sobrien		  sec->reloc_count * sizeof (struct internal_reloc));
53484865Sobrien	  return internal_relocs;
53584865Sobrien	}
53684865Sobrien    }
53784865Sobrien
53884865Sobrien  return _bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
53984865Sobrien					 require_internal, internal_relocs);
54084865Sobrien}
54184865Sobrien
542218822Sdim/* This function is used to add symbols from a dynamic object to the
543218822Sdim   global symbol table.  */
54484865Sobrien
545130561Sobrienstatic bfd_boolean
546218822Sdimxcoff_link_add_dynamic_symbols (bfd *abfd, struct bfd_link_info *info)
54784865Sobrien{
54884865Sobrien  asection *lsec;
54994536Sobrien  bfd_byte *contents;
55084865Sobrien  struct internal_ldhdr ldhdr;
55184865Sobrien  const char *strings;
55294536Sobrien  bfd_byte *elsym, *elsymend;
553218822Sdim  struct xcoff_import_file *n;
554218822Sdim  const char *bname;
555218822Sdim  const char *mname;
556218822Sdim  const char *s;
557218822Sdim  unsigned int c;
558218822Sdim  struct xcoff_import_file **pp;
55984865Sobrien
560218822Sdim  /* We can only handle a dynamic object if we are generating an XCOFF
561218822Sdim     output file.  */
562218822Sdim   if (info->hash->creator != abfd->xvec)
563218822Sdim    {
564218822Sdim      (*_bfd_error_handler)
565218822Sdim	(_("%s: XCOFF shared object when not producing XCOFF output"),
566218822Sdim	 bfd_get_filename (abfd));
567218822Sdim      bfd_set_error (bfd_error_invalid_operation);
568218822Sdim      return FALSE;
569218822Sdim    }
57084865Sobrien
571218822Sdim  /* The symbols we use from a dynamic object are not the symbols in
572218822Sdim     the normal symbol table, but, rather, the symbols in the export
573218822Sdim     table.  If there is a global symbol in a dynamic object which is
574218822Sdim     not in the export table, the loader will not be able to find it,
575218822Sdim     so we don't want to find it either.  Also, on AIX 4.1.3, shr.o in
576218822Sdim     libc.a has symbols in the export table which are not in the
577218822Sdim     symbol table.  */
578218822Sdim
579218822Sdim  /* Read in the .loader section.  FIXME: We should really use the
580218822Sdim     o_snloader field in the a.out header, rather than grabbing the
581218822Sdim     section by name.  */
58284865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
58384865Sobrien  if (lsec == NULL)
58484865Sobrien    {
585218822Sdim      (*_bfd_error_handler)
586218822Sdim	(_("%s: dynamic object with no .loader section"),
587218822Sdim	 bfd_get_filename (abfd));
588218822Sdim      bfd_set_error (bfd_error_no_symbols);
589218822Sdim      return FALSE;
59084865Sobrien    }
59184865Sobrien
59284865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
593130561Sobrien    return FALSE;
59494536Sobrien  contents = coff_section_data (abfd, lsec)->contents;
59584865Sobrien
596218822Sdim  /* Remove the sections from this object, so that they do not get
597218822Sdim     included in the link.  */
598218822Sdim  bfd_section_list_clear (abfd);
599218822Sdim
60094536Sobrien  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
60184865Sobrien
60294536Sobrien  strings = (char *) contents + ldhdr.l_stoff;
60384865Sobrien
60494536Sobrien  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
60594536Sobrien
60694536Sobrien  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
607218822Sdim
60894536Sobrien  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
60984865Sobrien    {
61084865Sobrien      struct internal_ldsym ldsym;
61184865Sobrien      char nambuf[SYMNMLEN + 1];
61284865Sobrien      const char *name;
613218822Sdim      struct xcoff_link_hash_entry *h;
61484865Sobrien
61594536Sobrien      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
61684865Sobrien
61784865Sobrien      /* We are only interested in exported symbols.  */
61884865Sobrien      if ((ldsym.l_smtype & L_EXPORT) == 0)
61984865Sobrien	continue;
62084865Sobrien
62184865Sobrien      if (ldsym._l._l_l._l_zeroes == 0)
62284865Sobrien	name = strings + ldsym._l._l_l._l_offset;
62384865Sobrien      else
62484865Sobrien	{
62584865Sobrien	  memcpy (nambuf, ldsym._l._l_name, SYMNMLEN);
62684865Sobrien	  nambuf[SYMNMLEN] = '\0';
62784865Sobrien	  name = nambuf;
62884865Sobrien	}
62984865Sobrien
630218822Sdim      /* Normally we could not call xcoff_link_hash_lookup in an add
631218822Sdim	 symbols routine, since we might not be using an XCOFF hash
632218822Sdim	 table.  However, we verified above that we are using an XCOFF
633218822Sdim	 hash table.  */
63484865Sobrien
635218822Sdim      h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, TRUE,
636218822Sdim				  TRUE, TRUE);
637218822Sdim      if (h == NULL)
638218822Sdim	return FALSE;
639218822Sdim
640218822Sdim      h->flags |= XCOFF_DEF_DYNAMIC;
641218822Sdim
642218822Sdim      /* If the symbol is undefined, and the BFD it was found in is
643218822Sdim	 not a dynamic object, change the BFD to this dynamic object,
644218822Sdim	 so that we can get the correct import file ID.  */
645218822Sdim      if ((h->root.type == bfd_link_hash_undefined
646218822Sdim	   || h->root.type == bfd_link_hash_undefweak)
647218822Sdim	  && (h->root.u.undef.abfd == NULL
648218822Sdim	      || (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
649218822Sdim	h->root.u.undef.abfd = abfd;
650218822Sdim
651218822Sdim      if (h->root.type == bfd_link_hash_new)
65284865Sobrien	{
653218822Sdim	  h->root.type = bfd_link_hash_undefined;
654218822Sdim	  h->root.u.undef.abfd = abfd;
655218822Sdim	  /* We do not want to add this to the undefined symbol list.  */
65684865Sobrien	}
657218822Sdim
658218822Sdim      if (h->smclas == XMC_UA
659218822Sdim	  || h->root.type == bfd_link_hash_undefined
660218822Sdim	  || h->root.type == bfd_link_hash_undefweak)
661218822Sdim	h->smclas = ldsym.l_smclas;
662218822Sdim
663218822Sdim      /* Unless this is an XMC_XO symbol, we don't bother to actually
664218822Sdim	 define it, since we don't have a section to put it in anyhow.
665218822Sdim	 Instead, the relocation routines handle the DEF_DYNAMIC flag
666218822Sdim	 correctly.  */
667218822Sdim
668218822Sdim      if (h->smclas == XMC_XO
669218822Sdim	  && (h->root.type == bfd_link_hash_undefined
670218822Sdim	      || h->root.type == bfd_link_hash_undefweak))
671218822Sdim	{
672218822Sdim	  /* This symbol has an absolute value.  */
673218822Sdim	  h->root.type = bfd_link_hash_defined;
674218822Sdim	  h->root.u.def.section = bfd_abs_section_ptr;
675218822Sdim	  h->root.u.def.value = ldsym.l_value;
676218822Sdim	}
677218822Sdim
678218822Sdim      /* If this symbol defines a function descriptor, then it
679218822Sdim	 implicitly defines the function code as well.  */
680218822Sdim      if (h->smclas == XMC_DS
681218822Sdim	  || (h->smclas == XMC_XO && name[0] != '.'))
682218822Sdim	h->flags |= XCOFF_DESCRIPTOR;
683218822Sdim      if ((h->flags & XCOFF_DESCRIPTOR) != 0)
684218822Sdim	{
685218822Sdim	  struct xcoff_link_hash_entry *hds;
686218822Sdim
687218822Sdim	  hds = h->descriptor;
688218822Sdim	  if (hds == NULL)
689218822Sdim	    {
690218822Sdim	      char *dsnm;
691218822Sdim
692218822Sdim	      dsnm = bfd_malloc ((bfd_size_type) strlen (name) + 2);
693218822Sdim	      if (dsnm == NULL)
694218822Sdim		return FALSE;
695218822Sdim	      dsnm[0] = '.';
696218822Sdim	      strcpy (dsnm + 1, name);
697218822Sdim	      hds = xcoff_link_hash_lookup (xcoff_hash_table (info), dsnm,
698218822Sdim					    TRUE, TRUE, TRUE);
699218822Sdim	      free (dsnm);
700218822Sdim	      if (hds == NULL)
701218822Sdim		return FALSE;
702218822Sdim
703218822Sdim	      if (hds->root.type == bfd_link_hash_new)
704218822Sdim		{
705218822Sdim		  hds->root.type = bfd_link_hash_undefined;
706218822Sdim		  hds->root.u.undef.abfd = abfd;
707218822Sdim		  /* We do not want to add this to the undefined
708218822Sdim		     symbol list.  */
709218822Sdim		}
710218822Sdim
711218822Sdim	      hds->descriptor = h;
712218822Sdim	      h->descriptor = hds;
713218822Sdim	    }
714218822Sdim
715218822Sdim	  hds->flags |= XCOFF_DEF_DYNAMIC;
716218822Sdim	  if (hds->smclas == XMC_UA)
717218822Sdim	    hds->smclas = XMC_PR;
718218822Sdim
719218822Sdim	  /* An absolute symbol appears to actually define code, not a
720218822Sdim	     function descriptor.  This is how some math functions are
721218822Sdim	     implemented on AIX 4.1.  */
722218822Sdim	  if (h->smclas == XMC_XO
723218822Sdim	      && (hds->root.type == bfd_link_hash_undefined
724218822Sdim		  || hds->root.type == bfd_link_hash_undefweak))
725218822Sdim	    {
726218822Sdim	      hds->smclas = XMC_XO;
727218822Sdim	      hds->root.type = bfd_link_hash_defined;
728218822Sdim	      hds->root.u.def.section = bfd_abs_section_ptr;
729218822Sdim	      hds->root.u.def.value = ldsym.l_value;
730218822Sdim	    }
731218822Sdim	}
73284865Sobrien    }
73384865Sobrien
73494536Sobrien  if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
73584865Sobrien    {
73684865Sobrien      free (coff_section_data (abfd, lsec)->contents);
73784865Sobrien      coff_section_data (abfd, lsec)->contents = NULL;
73884865Sobrien    }
73984865Sobrien
740218822Sdim  /* Record this file in the import files.  */
741218822Sdim  n = bfd_alloc (abfd, (bfd_size_type) sizeof (struct xcoff_import_file));
742218822Sdim  if (n == NULL)
743218822Sdim    return FALSE;
744218822Sdim  n->next = NULL;
74584865Sobrien
746218822Sdim  /* For some reason, the path entry in the import file list for a
747218822Sdim     shared object appears to always be empty.  The file name is the
748218822Sdim     base name.  */
749218822Sdim  n->path = "";
750218822Sdim  if (abfd->my_archive == NULL)
75184865Sobrien    {
752218822Sdim      bname = bfd_get_filename (abfd);
753218822Sdim      mname = "";
75484865Sobrien    }
755218822Sdim  else
75684865Sobrien    {
757218822Sdim      bname = bfd_get_filename (abfd->my_archive);
758218822Sdim      mname = bfd_get_filename (abfd);
75984865Sobrien    }
760218822Sdim  s = strrchr (bname, '/');
761218822Sdim  if (s != NULL)
762218822Sdim    bname = s + 1;
763218822Sdim  n->file = bname;
764218822Sdim  n->member = mname;
76584865Sobrien
766218822Sdim  /* We start c at 1 because the first import file number is reserved
767218822Sdim     for LIBPATH.  */
768218822Sdim  for (pp = &xcoff_hash_table (info)->imports, c = 1;
769218822Sdim       *pp != NULL;
770218822Sdim       pp = &(*pp)->next, ++c)
771218822Sdim    ;
772218822Sdim  *pp = n;
77384865Sobrien
774218822Sdim  xcoff_data (abfd)->import_file_id = c;
77584865Sobrien
776218822Sdim  return TRUE;
77784865Sobrien}
77884865Sobrien
77994536Sobrien/* xcoff_link_create_extra_sections
78084865Sobrien
78194536Sobrien   Takes care of creating the .loader, .gl, .ds, .debug and sections.  */
78284865Sobrien
783130561Sobrienstatic bfd_boolean
784218822Sdimxcoff_link_create_extra_sections (bfd * abfd, struct bfd_link_info *info)
78584865Sobrien{
786130561Sobrien  bfd_boolean return_value = FALSE;
78784865Sobrien
78894536Sobrien  if (info->hash->creator == abfd->xvec)
78984865Sobrien    {
79084865Sobrien      /* We need to build a .loader section, so we do it here.  This
79184865Sobrien	 won't work if we're producing an XCOFF output file with no
79284865Sobrien	 XCOFF input files.  FIXME.  */
79394536Sobrien
79484865Sobrien      if (xcoff_hash_table (info)->loader_section == NULL)
79584865Sobrien	{
79684865Sobrien	  asection *lsec;
797218822Sdim	  flagword flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
79884865Sobrien
799218822Sdim	  lsec = bfd_make_section_anyway_with_flags (abfd, ".loader", flags);
80084865Sobrien	  if (lsec == NULL)
801218822Sdim	    goto end_return;
802218822Sdim
80384865Sobrien	  xcoff_hash_table (info)->loader_section = lsec;
80484865Sobrien	}
80594536Sobrien
80684865Sobrien      /* Likewise for the linkage section.  */
80784865Sobrien      if (xcoff_hash_table (info)->linkage_section == NULL)
80884865Sobrien	{
80984865Sobrien	  asection *lsec;
810218822Sdim	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
811218822Sdim			    | SEC_IN_MEMORY);
81284865Sobrien
813218822Sdim	  lsec = bfd_make_section_anyway_with_flags (abfd, ".gl", flags);
81484865Sobrien	  if (lsec == NULL)
815218822Sdim	    goto end_return;
81694536Sobrien
81784865Sobrien	  xcoff_hash_table (info)->linkage_section = lsec;
81884865Sobrien	  lsec->alignment_power = 2;
81984865Sobrien	}
82094536Sobrien
82184865Sobrien      /* Likewise for the TOC section.  */
82284865Sobrien      if (xcoff_hash_table (info)->toc_section == NULL)
82384865Sobrien	{
82484865Sobrien	  asection *tsec;
825218822Sdim	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
826218822Sdim			    | SEC_IN_MEMORY);
82784865Sobrien
828218822Sdim	  tsec = bfd_make_section_anyway_with_flags (abfd, ".tc", flags);
82984865Sobrien	  if (tsec == NULL)
830218822Sdim	    goto end_return;
83194536Sobrien
83284865Sobrien	  xcoff_hash_table (info)->toc_section = tsec;
83384865Sobrien	  tsec->alignment_power = 2;
83484865Sobrien	}
83594536Sobrien
83684865Sobrien      /* Likewise for the descriptor section.  */
83784865Sobrien      if (xcoff_hash_table (info)->descriptor_section == NULL)
83884865Sobrien	{
83984865Sobrien	  asection *dsec;
840218822Sdim	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
841218822Sdim			    | SEC_IN_MEMORY);
84284865Sobrien
843218822Sdim	  dsec = bfd_make_section_anyway_with_flags (abfd, ".ds", flags);
84484865Sobrien	  if (dsec == NULL)
845218822Sdim	    goto end_return;
84694536Sobrien
84784865Sobrien	  xcoff_hash_table (info)->descriptor_section = dsec;
84884865Sobrien	  dsec->alignment_power = 2;
84984865Sobrien	}
85094536Sobrien
85184865Sobrien      /* Likewise for the .debug section.  */
85284865Sobrien      if (xcoff_hash_table (info)->debug_section == NULL
85384865Sobrien	  && info->strip != strip_all)
85484865Sobrien	{
85584865Sobrien	  asection *dsec;
856218822Sdim	  flagword flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
85784865Sobrien
858218822Sdim	  dsec = bfd_make_section_anyway_with_flags (abfd, ".debug", flags);
85984865Sobrien	  if (dsec == NULL)
860218822Sdim	    goto end_return;
861218822Sdim
86284865Sobrien	  xcoff_hash_table (info)->debug_section = dsec;
86384865Sobrien	}
86484865Sobrien    }
86584865Sobrien
866130561Sobrien  return_value = TRUE;
86794536Sobrien
86894536Sobrien end_return:
86994536Sobrien
87094536Sobrien  return return_value;
87194536Sobrien}
87294536Sobrien
873218822Sdim/* Returns the index of reloc in RELOCS with the least address greater
874218822Sdim   than or equal to ADDRESS.  The relocs are sorted by address.  */
875218822Sdim
876218822Sdimstatic bfd_size_type
877218822Sdimxcoff_find_reloc (struct internal_reloc *relocs,
878218822Sdim		  bfd_size_type count,
879218822Sdim		  bfd_vma address)
880218822Sdim{
881218822Sdim  bfd_size_type min, max, this;
882218822Sdim
883218822Sdim  if (count < 2)
884218822Sdim    {
885218822Sdim      if (count == 1 && relocs[0].r_vaddr < address)
886218822Sdim	return 1;
887218822Sdim      else
888218822Sdim	return 0;
889218822Sdim    }
890218822Sdim
891218822Sdim  min = 0;
892218822Sdim  max = count;
893218822Sdim
894218822Sdim  /* Do a binary search over (min,max].  */
895218822Sdim  while (min + 1 < max)
896218822Sdim    {
897218822Sdim      bfd_vma raddr;
898218822Sdim
899218822Sdim      this = (max + min) / 2;
900218822Sdim      raddr = relocs[this].r_vaddr;
901218822Sdim      if (raddr > address)
902218822Sdim	max = this;
903218822Sdim      else if (raddr < address)
904218822Sdim	min = this;
905218822Sdim      else
906218822Sdim	{
907218822Sdim	  min = this;
908218822Sdim	  break;
909218822Sdim	}
910218822Sdim    }
911218822Sdim
912218822Sdim  if (relocs[min].r_vaddr < address)
913218822Sdim    return min + 1;
914218822Sdim
915218822Sdim  while (min > 0
916218822Sdim	 && relocs[min - 1].r_vaddr == address)
917218822Sdim    --min;
918218822Sdim
919218822Sdim  return min;
920218822Sdim}
921218822Sdim
92294536Sobrien/* Add all the symbols from an object file to the hash table.
92394536Sobrien
92494536Sobrien   XCOFF is a weird format.  A normal XCOFF .o files will have three
92594536Sobrien   COFF sections--.text, .data, and .bss--but each COFF section will
92694536Sobrien   contain many csects.  These csects are described in the symbol
92794536Sobrien   table.  From the linker's point of view, each csect must be
92894536Sobrien   considered a section in its own right.  For example, a TOC entry is
92994536Sobrien   handled as a small XMC_TC csect.  The linker must be able to merge
93094536Sobrien   different TOC entries together, which means that it must be able to
93194536Sobrien   extract the XMC_TC csects from the .data section of the input .o
93294536Sobrien   file.
93394536Sobrien
93494536Sobrien   From the point of view of our linker, this is, of course, a hideous
93594536Sobrien   nightmare.  We cope by actually creating sections for each csect,
93694536Sobrien   and discarding the original sections.  We then have to handle the
93794536Sobrien   relocation entries carefully, since the only way to tell which
93894536Sobrien   csect they belong to is to examine the address.  */
93994536Sobrien
940130561Sobrienstatic bfd_boolean
941218822Sdimxcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
94294536Sobrien{
94394536Sobrien  unsigned int n_tmask;
94494536Sobrien  unsigned int n_btshft;
945130561Sobrien  bfd_boolean default_copy;
94694536Sobrien  bfd_size_type symcount;
94794536Sobrien  struct xcoff_link_hash_entry **sym_hash;
94894536Sobrien  asection **csect_cache;
94994536Sobrien  bfd_size_type linesz;
95094536Sobrien  asection *o;
95194536Sobrien  asection *last_real;
952130561Sobrien  bfd_boolean keep_syms;
95394536Sobrien  asection *csect;
95494536Sobrien  unsigned int csect_index;
95594536Sobrien  asection *first_csect;
95694536Sobrien  bfd_size_type symesz;
95794536Sobrien  bfd_byte *esym;
95894536Sobrien  bfd_byte *esym_end;
95994536Sobrien  struct reloc_info_struct
96094536Sobrien  {
96194536Sobrien    struct internal_reloc *relocs;
96294536Sobrien    asection **csects;
96394536Sobrien    bfd_byte *linenos;
96494536Sobrien  } *reloc_info = NULL;
96594536Sobrien  bfd_size_type amt;
96694536Sobrien
96794536Sobrien  keep_syms = obj_coff_keep_syms (abfd);
96894536Sobrien
96984865Sobrien  if ((abfd->flags & DYNAMIC) != 0
97084865Sobrien      && ! info->static_link)
97194536Sobrien    {
97294536Sobrien      if (! xcoff_link_add_dynamic_symbols (abfd, info))
973130561Sobrien	return FALSE;
97494536Sobrien    }
97594536Sobrien
976218822Sdim  /* Create the loader, toc, gl, ds and debug sections, if needed.  */
977130561Sobrien  if (! xcoff_link_create_extra_sections (abfd, info))
978104834Sobrien    goto error_return;
97994536Sobrien
98094536Sobrien  if ((abfd->flags & DYNAMIC) != 0
98194536Sobrien      && ! info->static_link)
982130561Sobrien    return TRUE;
98384865Sobrien
98484865Sobrien  n_tmask = coff_data (abfd)->local_n_tmask;
98584865Sobrien  n_btshft = coff_data (abfd)->local_n_btshft;
98684865Sobrien
98784865Sobrien  /* Define macros so that ISFCN, et. al., macros work correctly.  */
98884865Sobrien#define N_TMASK n_tmask
98984865Sobrien#define N_BTSHFT n_btshft
99084865Sobrien
99184865Sobrien  if (info->keep_memory)
992130561Sobrien    default_copy = FALSE;
99384865Sobrien  else
994130561Sobrien    default_copy = TRUE;
99584865Sobrien
99684865Sobrien  symcount = obj_raw_syment_count (abfd);
99784865Sobrien
99884865Sobrien  /* We keep a list of the linker hash table entries that correspond
99984865Sobrien     to each external symbol.  */
100094536Sobrien  amt = symcount * sizeof (struct xcoff_link_hash_entry *);
1001218822Sdim  sym_hash = bfd_zalloc (abfd, amt);
100284865Sobrien  if (sym_hash == NULL && symcount != 0)
100384865Sobrien    goto error_return;
100484865Sobrien  coff_data (abfd)->sym_hashes = (struct coff_link_hash_entry **) sym_hash;
100584865Sobrien
100684865Sobrien  /* Because of the weird stuff we are doing with XCOFF csects, we can
100784865Sobrien     not easily determine which section a symbol is in, so we store
100884865Sobrien     the information in the tdata for the input file.  */
100994536Sobrien  amt = symcount * sizeof (asection *);
1010218822Sdim  csect_cache = bfd_zalloc (abfd, amt);
101184865Sobrien  if (csect_cache == NULL && symcount != 0)
101284865Sobrien    goto error_return;
101384865Sobrien  xcoff_data (abfd)->csects = csect_cache;
101484865Sobrien
101584865Sobrien  /* While splitting sections into csects, we need to assign the
101684865Sobrien     relocs correctly.  The relocs and the csects must both be in
101784865Sobrien     order by VMA within a given section, so we handle this by
101884865Sobrien     scanning along the relocs as we process the csects.  We index
101984865Sobrien     into reloc_info using the section target_index.  */
102094536Sobrien  amt = abfd->section_count + 1;
102194536Sobrien  amt *= sizeof (struct reloc_info_struct);
1022218822Sdim  reloc_info = bfd_zmalloc (amt);
102384865Sobrien  if (reloc_info == NULL)
102484865Sobrien    goto error_return;
102584865Sobrien
102684865Sobrien  /* Read in the relocs and line numbers for each section.  */
102784865Sobrien  linesz = bfd_coff_linesz (abfd);
102884865Sobrien  last_real = NULL;
102984865Sobrien  for (o = abfd->sections; o != NULL; o = o->next)
103084865Sobrien    {
1031218822Sdim      last_real = o;
103294536Sobrien
103384865Sobrien      if ((o->flags & SEC_RELOC) != 0)
103484865Sobrien	{
103584865Sobrien	  reloc_info[o->target_index].relocs =
1036218822Sdim	    xcoff_read_internal_relocs (abfd, o, TRUE, NULL, FALSE, NULL);
103794536Sobrien	  amt = o->reloc_count;
103894536Sobrien	  amt *= sizeof (asection *);
1039218822Sdim	  reloc_info[o->target_index].csects = bfd_zmalloc (amt);
104084865Sobrien	  if (reloc_info[o->target_index].csects == NULL)
104184865Sobrien	    goto error_return;
104284865Sobrien	}
104384865Sobrien
104484865Sobrien      if ((info->strip == strip_none || info->strip == strip_some)
104584865Sobrien	  && o->lineno_count > 0)
104684865Sobrien	{
104784865Sobrien	  bfd_byte *linenos;
104884865Sobrien
104994536Sobrien	  amt = linesz * o->lineno_count;
1050218822Sdim	  linenos = bfd_malloc (amt);
105184865Sobrien	  if (linenos == NULL)
105284865Sobrien	    goto error_return;
105384865Sobrien	  reloc_info[o->target_index].linenos = linenos;
105484865Sobrien	  if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
105594536Sobrien	      || bfd_bread (linenos, amt, abfd) != amt)
105684865Sobrien	    goto error_return;
105784865Sobrien	}
105884865Sobrien    }
105984865Sobrien
106084865Sobrien  /* Don't let the linker relocation routines discard the symbols.  */
1061130561Sobrien  obj_coff_keep_syms (abfd) = TRUE;
106284865Sobrien
106384865Sobrien  csect = NULL;
106484865Sobrien  csect_index = 0;
106584865Sobrien  first_csect = NULL;
106684865Sobrien
106784865Sobrien  symesz = bfd_coff_symesz (abfd);
106884865Sobrien  BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
106984865Sobrien  esym = (bfd_byte *) obj_coff_external_syms (abfd);
107084865Sobrien  esym_end = esym + symcount * symesz;
107194536Sobrien
107284865Sobrien  while (esym < esym_end)
107384865Sobrien    {
107484865Sobrien      struct internal_syment sym;
107584865Sobrien      union internal_auxent aux;
107684865Sobrien      const char *name;
107784865Sobrien      char buf[SYMNMLEN + 1];
107884865Sobrien      int smtyp;
107984865Sobrien      flagword flags;
108084865Sobrien      asection *section;
108184865Sobrien      bfd_vma value;
108284865Sobrien      struct xcoff_link_hash_entry *set_toc;
108384865Sobrien
1084218822Sdim      bfd_coff_swap_sym_in (abfd, (void *) esym, (void *) &sym);
108584865Sobrien
108684865Sobrien      /* In this pass we are only interested in symbols with csect
108794536Sobrien	 information.  */
108884865Sobrien      if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
108984865Sobrien	{
109094536Sobrien	  /* Set csect_cache,
109194536Sobrien	     Normally csect is a .pr, .rw  etc. created in the loop
109294536Sobrien	     If C_FILE or first time, handle special
109394536Sobrien
109494536Sobrien	     Advance esym, sym_hash, csect_hash ptr's
109594536Sobrien	     Keep track of the last_symndx for the current file.  */
109684865Sobrien	  if (sym.n_sclass == C_FILE && csect != NULL)
109784865Sobrien	    {
109884865Sobrien	      xcoff_section_data (abfd, csect)->last_symndx =
109984865Sobrien		((esym
110084865Sobrien		  - (bfd_byte *) obj_coff_external_syms (abfd))
110184865Sobrien		 / symesz);
110284865Sobrien	      csect = NULL;
110384865Sobrien	    }
110484865Sobrien
110584865Sobrien	  if (csect != NULL)
110684865Sobrien	    *csect_cache = csect;
110784865Sobrien	  else if (first_csect == NULL || sym.n_sclass == C_FILE)
110884865Sobrien	    *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
110984865Sobrien	  else
111084865Sobrien	    *csect_cache = NULL;
111184865Sobrien	  esym += (sym.n_numaux + 1) * symesz;
111284865Sobrien	  sym_hash += sym.n_numaux + 1;
111384865Sobrien	  csect_cache += sym.n_numaux + 1;
111494536Sobrien
111584865Sobrien	  continue;
111684865Sobrien	}
111784865Sobrien
111884865Sobrien      name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
111994536Sobrien
112084865Sobrien      if (name == NULL)
112184865Sobrien	goto error_return;
112284865Sobrien
112384865Sobrien      /* If this symbol has line number information attached to it,
1124130561Sobrien	 and we're not stripping it, count the number of entries and
1125130561Sobrien	 add them to the count for this csect.  In the final link pass
1126130561Sobrien	 we are going to attach line number information by symbol,
1127130561Sobrien	 rather than by section, in order to more easily handle
1128130561Sobrien	 garbage collection.  */
112984865Sobrien      if ((info->strip == strip_none || info->strip == strip_some)
113084865Sobrien	  && sym.n_numaux > 1
113184865Sobrien	  && csect != NULL
113284865Sobrien	  && ISFCN (sym.n_type))
113384865Sobrien	{
113484865Sobrien	  union internal_auxent auxlin;
113584865Sobrien
1136218822Sdim	  bfd_coff_swap_aux_in (abfd, (void *) (esym + symesz),
113784865Sobrien				sym.n_type, sym.n_sclass,
1138218822Sdim				0, sym.n_numaux, (void *) &auxlin);
113994536Sobrien
114084865Sobrien	  if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
114184865Sobrien	    {
114284865Sobrien	      asection *enclosing;
114394536Sobrien	      bfd_signed_vma linoff;
114484865Sobrien
114584865Sobrien	      enclosing = xcoff_section_data (abfd, csect)->enclosing;
114684865Sobrien	      if (enclosing == NULL)
114784865Sobrien		{
114884865Sobrien		  (*_bfd_error_handler)
1149218822Sdim		    (_("%B: `%s' has line numbers but no enclosing section"),
1150218822Sdim		     abfd, name);
115184865Sobrien		  bfd_set_error (bfd_error_bad_value);
115284865Sobrien		  goto error_return;
115384865Sobrien		}
115484865Sobrien	      linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
115584865Sobrien			- enclosing->line_filepos);
1156218822Sdim	      /* Explicit cast to bfd_signed_vma for compiler.  */
115794536Sobrien	      if (linoff < (bfd_signed_vma) (enclosing->lineno_count * linesz))
115884865Sobrien		{
115984865Sobrien		  struct internal_lineno lin;
116084865Sobrien		  bfd_byte *linpstart;
116184865Sobrien
116284865Sobrien		  linpstart = (reloc_info[enclosing->target_index].linenos
116384865Sobrien			       + linoff);
1164218822Sdim		  bfd_coff_swap_lineno_in (abfd, (void *) linpstart, (void *) &lin);
116584865Sobrien		  if (lin.l_lnno == 0
116684865Sobrien		      && ((bfd_size_type) lin.l_addr.l_symndx
116784865Sobrien			  == ((esym
116884865Sobrien			       - (bfd_byte *) obj_coff_external_syms (abfd))
116984865Sobrien			      / symesz)))
117084865Sobrien		    {
117184865Sobrien		      bfd_byte *linpend, *linp;
117284865Sobrien
117384865Sobrien		      linpend = (reloc_info[enclosing->target_index].linenos
117484865Sobrien				 + enclosing->lineno_count * linesz);
117584865Sobrien		      for (linp = linpstart + linesz;
117684865Sobrien			   linp < linpend;
117784865Sobrien			   linp += linesz)
117884865Sobrien			{
1179218822Sdim			  bfd_coff_swap_lineno_in (abfd, (void *) linp,
1180218822Sdim						   (void *) &lin);
118184865Sobrien			  if (lin.l_lnno == 0)
118284865Sobrien			    break;
118384865Sobrien			}
118484865Sobrien		      csect->lineno_count += (linp - linpstart) / linesz;
118584865Sobrien		      /* The setting of line_filepos will only be
118694536Sobrien			 useful if all the line number entries for a
118794536Sobrien			 csect are contiguous; this only matters for
118894536Sobrien			 error reporting.  */
118984865Sobrien		      if (csect->line_filepos == 0)
119084865Sobrien			csect->line_filepos =
119184865Sobrien			  auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
119284865Sobrien		    }
119384865Sobrien		}
119484865Sobrien	    }
119584865Sobrien	}
119684865Sobrien
119784865Sobrien      /* Pick up the csect auxiliary information.  */
119884865Sobrien      if (sym.n_numaux == 0)
119984865Sobrien	{
120084865Sobrien	  (*_bfd_error_handler)
1201218822Sdim	    (_("%B: class %d symbol `%s' has no aux entries"),
1202218822Sdim	     abfd, sym.n_sclass, name);
120384865Sobrien	  bfd_set_error (bfd_error_bad_value);
120484865Sobrien	  goto error_return;
120584865Sobrien	}
120684865Sobrien
120784865Sobrien      bfd_coff_swap_aux_in (abfd,
1208218822Sdim			    (void *) (esym + symesz * sym.n_numaux),
120984865Sobrien			    sym.n_type, sym.n_sclass,
121084865Sobrien			    sym.n_numaux - 1, sym.n_numaux,
1211218822Sdim			    (void *) &aux);
121284865Sobrien
121384865Sobrien      smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
121484865Sobrien
121584865Sobrien      flags = BSF_GLOBAL;
121684865Sobrien      section = NULL;
121784865Sobrien      value = 0;
121884865Sobrien      set_toc = NULL;
121984865Sobrien
122084865Sobrien      switch (smtyp)
122184865Sobrien	{
122284865Sobrien	default:
122384865Sobrien	  (*_bfd_error_handler)
1224218822Sdim	    (_("%B: symbol `%s' has unrecognized csect type %d"),
1225218822Sdim	     abfd, name, smtyp);
122684865Sobrien	  bfd_set_error (bfd_error_bad_value);
122784865Sobrien	  goto error_return;
122884865Sobrien
122984865Sobrien	case XTY_ER:
123084865Sobrien	  /* This is an external reference.  */
123184865Sobrien	  if (sym.n_sclass == C_HIDEXT
123284865Sobrien	      || sym.n_scnum != N_UNDEF
123384865Sobrien	      || aux.x_csect.x_scnlen.l != 0)
123484865Sobrien	    {
123584865Sobrien	      (*_bfd_error_handler)
1236218822Sdim		(_("%B: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"),
1237218822Sdim		 abfd, name, sym.n_sclass, sym.n_scnum,
123884865Sobrien		 aux.x_csect.x_scnlen.l);
123984865Sobrien	      bfd_set_error (bfd_error_bad_value);
124084865Sobrien	      goto error_return;
124184865Sobrien	    }
124284865Sobrien
124384865Sobrien	  /* An XMC_XO external reference is actually a reference to
1244130561Sobrien	     an absolute location.  */
124584865Sobrien	  if (aux.x_csect.x_smclas != XMC_XO)
124684865Sobrien	    section = bfd_und_section_ptr;
124784865Sobrien	  else
124884865Sobrien	    {
124984865Sobrien	      section = bfd_abs_section_ptr;
125084865Sobrien	      value = sym.n_value;
125184865Sobrien	    }
125284865Sobrien	  break;
125384865Sobrien
125484865Sobrien	case XTY_SD:
125584865Sobrien	  /* This is a csect definition.  */
125684865Sobrien	  if (csect != NULL)
125784865Sobrien	    {
125884865Sobrien	      xcoff_section_data (abfd, csect)->last_symndx =
125994536Sobrien		((esym - (bfd_byte *) obj_coff_external_syms (abfd)) / symesz);
126084865Sobrien	    }
126184865Sobrien
126284865Sobrien	  csect = NULL;
126394536Sobrien	  csect_index = -(unsigned) 1;
126484865Sobrien
126584865Sobrien	  /* When we see a TOC anchor, we record the TOC value.  */
126684865Sobrien	  if (aux.x_csect.x_smclas == XMC_TC0)
126784865Sobrien	    {
126884865Sobrien	      if (sym.n_sclass != C_HIDEXT
126984865Sobrien		  || aux.x_csect.x_scnlen.l != 0)
127084865Sobrien		{
127184865Sobrien		  (*_bfd_error_handler)
1272218822Sdim		    (_("%B: XMC_TC0 symbol `%s' is class %d scnlen %d"),
1273218822Sdim		     abfd, name, sym.n_sclass, aux.x_csect.x_scnlen.l);
127484865Sobrien		  bfd_set_error (bfd_error_bad_value);
127584865Sobrien		  goto error_return;
127684865Sobrien		}
127784865Sobrien	      xcoff_data (abfd)->toc = sym.n_value;
127884865Sobrien	    }
127984865Sobrien
128084865Sobrien	  /* We must merge TOC entries for the same symbol.  We can
128184865Sobrien	     merge two TOC entries if they are both C_HIDEXT, they
128294536Sobrien	     both have the same name, they are both 4 or 8 bytes long, and
128384865Sobrien	     they both have a relocation table entry for an external
128484865Sobrien	     symbol with the same name.  Unfortunately, this means
128594536Sobrien	     that we must look through the relocations.  Ick.
128694536Sobrien
128794536Sobrien	     Logic for 32 bit vs 64 bit.
128894536Sobrien	     32 bit has a csect length of 4 for TOC
128994536Sobrien	     64 bit has a csect length of 8 for TOC
129094536Sobrien
129194536Sobrien	     The conditions to get past the if-check are not that bad.
129294536Sobrien	     They are what is used to create the TOC csects in the first
129394536Sobrien	     place.  */
129484865Sobrien	  if (aux.x_csect.x_smclas == XMC_TC
129584865Sobrien	      && sym.n_sclass == C_HIDEXT
129694536Sobrien	      && info->hash->creator == abfd->xvec
129794536Sobrien	      && ((bfd_xcoff_is_xcoff32 (abfd)
129894536Sobrien		   && aux.x_csect.x_scnlen.l == 4)
129994536Sobrien		  || (bfd_xcoff_is_xcoff64 (abfd)
130094536Sobrien		      && aux.x_csect.x_scnlen.l == 8)))
130184865Sobrien	    {
130284865Sobrien	      asection *enclosing;
130384865Sobrien	      struct internal_reloc *relocs;
130484865Sobrien	      bfd_size_type relindx;
130584865Sobrien	      struct internal_reloc *rel;
130684865Sobrien
130784865Sobrien	      enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
130884865Sobrien	      if (enclosing == NULL)
130984865Sobrien		goto error_return;
131084865Sobrien
131184865Sobrien	      relocs = reloc_info[enclosing->target_index].relocs;
131294536Sobrien	      amt = enclosing->reloc_count;
131394536Sobrien	      relindx = xcoff_find_reloc (relocs, amt, sym.n_value);
131484865Sobrien	      rel = relocs + relindx;
131594536Sobrien
131694536Sobrien	      /* 32 bit R_POS r_size is 31
131794536Sobrien		 64 bit R_POS r_size is 63  */
131884865Sobrien	      if (relindx < enclosing->reloc_count
131984865Sobrien		  && rel->r_vaddr == (bfd_vma) sym.n_value
132094536Sobrien		  && rel->r_type == R_POS
132194536Sobrien		  && ((bfd_xcoff_is_xcoff32 (abfd)
132294536Sobrien		       && rel->r_size == 31)
132394536Sobrien		      || (bfd_xcoff_is_xcoff64 (abfd)
132494536Sobrien			  && rel->r_size == 63)))
132584865Sobrien		{
132684865Sobrien		  bfd_byte *erelsym;
132794536Sobrien
132884865Sobrien		  struct internal_syment relsym;
132984865Sobrien
133084865Sobrien		  erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
133184865Sobrien			     + rel->r_symndx * symesz);
1332218822Sdim		  bfd_coff_swap_sym_in (abfd, (void *) erelsym, (void *) &relsym);
133384865Sobrien		  if (relsym.n_sclass == C_EXT)
133484865Sobrien		    {
133584865Sobrien		      const char *relname;
133684865Sobrien		      char relbuf[SYMNMLEN + 1];
1337130561Sobrien		      bfd_boolean copy;
133884865Sobrien		      struct xcoff_link_hash_entry *h;
133984865Sobrien
134084865Sobrien		      /* At this point we know that the TOC entry is
134184865Sobrien			 for an externally visible symbol.  */
134284865Sobrien		      relname = _bfd_coff_internal_syment_name (abfd, &relsym,
134384865Sobrien								relbuf);
134484865Sobrien		      if (relname == NULL)
134584865Sobrien			goto error_return;
134684865Sobrien
134784865Sobrien		      /* We only merge TOC entries if the TC name is
134894536Sobrien			 the same as the symbol name.  This handles
134994536Sobrien			 the normal case, but not common cases like
135094536Sobrien			 SYM.P4 which gcc generates to store SYM + 4
135194536Sobrien			 in the TOC.  FIXME.  */
135284865Sobrien		      if (strcmp (name, relname) == 0)
135384865Sobrien			{
135484865Sobrien			  copy = (! info->keep_memory
135584865Sobrien				  || relsym._n._n_n._n_zeroes != 0
135684865Sobrien				  || relsym._n._n_n._n_offset == 0);
135784865Sobrien			  h = xcoff_link_hash_lookup (xcoff_hash_table (info),
1358130561Sobrien						      relname, TRUE, copy,
1359130561Sobrien						      FALSE);
136084865Sobrien			  if (h == NULL)
136184865Sobrien			    goto error_return;
136284865Sobrien
136384865Sobrien			  /* At this point h->root.type could be
136484865Sobrien			     bfd_link_hash_new.  That should be OK,
136584865Sobrien			     since we know for sure that we will come
136684865Sobrien			     across this symbol as we step through the
136784865Sobrien			     file.  */
136884865Sobrien
136984865Sobrien			  /* We store h in *sym_hash for the
137084865Sobrien			     convenience of the relocate_section
137184865Sobrien			     function.  */
137284865Sobrien			  *sym_hash = h;
137384865Sobrien
137484865Sobrien			  if (h->toc_section != NULL)
137584865Sobrien			    {
137684865Sobrien			      asection **rel_csects;
137784865Sobrien
137884865Sobrien			      /* We already have a TOC entry for this
137984865Sobrien				 symbol, so we can just ignore this
138084865Sobrien				 one.  */
138184865Sobrien			      rel_csects =
138284865Sobrien				reloc_info[enclosing->target_index].csects;
138384865Sobrien			      rel_csects[relindx] = bfd_und_section_ptr;
138484865Sobrien			      break;
138584865Sobrien			    }
138684865Sobrien
138784865Sobrien			  /* We are about to create a TOC entry for
138884865Sobrien			     this symbol.  */
138984865Sobrien			  set_toc = h;
1390218822Sdim			}
1391218822Sdim		    }
1392218822Sdim		}
1393218822Sdim	    }
139484865Sobrien
139584865Sobrien	  {
139684865Sobrien	    asection *enclosing;
139784865Sobrien
139894536Sobrien	    /* We need to create a new section.  We get the name from
139994536Sobrien	       the csect storage mapping class, so that the linker can
140094536Sobrien	       accumulate similar csects together.  */
140194536Sobrien
140294536Sobrien	    csect = bfd_xcoff_create_csect_from_smclas(abfd, &aux, name);
140394536Sobrien	    if (NULL == csect)
1404218822Sdim	      goto error_return;
140584865Sobrien
140694536Sobrien	    /* The enclosing section is the main section : .data, .text
140794536Sobrien	       or .bss that the csect is coming from.  */
140884865Sobrien	    enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
140984865Sobrien	    if (enclosing == NULL)
141084865Sobrien	      goto error_return;
141194536Sobrien
141284865Sobrien	    if (! bfd_is_abs_section (enclosing)
141384865Sobrien		&& ((bfd_vma) sym.n_value < enclosing->vma
141484865Sobrien		    || ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
1415218822Sdim			> enclosing->vma + enclosing->size)))
141684865Sobrien	      {
141784865Sobrien		(*_bfd_error_handler)
1418218822Sdim		  (_("%B: csect `%s' not in enclosing section"),
1419218822Sdim		   abfd, name);
142084865Sobrien		bfd_set_error (bfd_error_bad_value);
142184865Sobrien		goto error_return;
142284865Sobrien	      }
142384865Sobrien	    csect->vma = sym.n_value;
142484865Sobrien	    csect->filepos = (enclosing->filepos
142584865Sobrien			      + sym.n_value
142684865Sobrien			      - enclosing->vma);
1427218822Sdim	    csect->size = aux.x_csect.x_scnlen.l;
142884865Sobrien	    csect->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
142984865Sobrien	    csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
143084865Sobrien
143184865Sobrien	    /* Record the enclosing section in the tdata for this new
143284865Sobrien	       section.  */
143394536Sobrien	    amt = sizeof (struct coff_section_tdata);
1434218822Sdim	    csect->used_by_bfd = bfd_zalloc (abfd, amt);
143584865Sobrien	    if (csect->used_by_bfd == NULL)
143684865Sobrien	      goto error_return;
143794536Sobrien	    amt = sizeof (struct xcoff_section_tdata);
143894536Sobrien	    coff_section_data (abfd, csect)->tdata = bfd_zalloc (abfd, amt);
143984865Sobrien	    if (coff_section_data (abfd, csect)->tdata == NULL)
144084865Sobrien	      goto error_return;
144184865Sobrien	    xcoff_section_data (abfd, csect)->enclosing = enclosing;
144284865Sobrien	    xcoff_section_data (abfd, csect)->lineno_count =
144384865Sobrien	      enclosing->lineno_count;
144484865Sobrien
144584865Sobrien	    if (enclosing->owner == abfd)
144684865Sobrien	      {
144784865Sobrien		struct internal_reloc *relocs;
144884865Sobrien		bfd_size_type relindx;
144984865Sobrien		struct internal_reloc *rel;
145084865Sobrien		asection **rel_csect;
145184865Sobrien
145284865Sobrien		relocs = reloc_info[enclosing->target_index].relocs;
145394536Sobrien		amt = enclosing->reloc_count;
145494536Sobrien		relindx = xcoff_find_reloc (relocs, amt, csect->vma);
145594536Sobrien
145684865Sobrien		rel = relocs + relindx;
145784865Sobrien		rel_csect = (reloc_info[enclosing->target_index].csects
145884865Sobrien			     + relindx);
145994536Sobrien
146084865Sobrien		csect->rel_filepos = (enclosing->rel_filepos
146184865Sobrien				      + relindx * bfd_coff_relsz (abfd));
146284865Sobrien		while (relindx < enclosing->reloc_count
146384865Sobrien		       && *rel_csect == NULL
1464218822Sdim		       && rel->r_vaddr < csect->vma + csect->size)
146584865Sobrien		  {
146694536Sobrien
146784865Sobrien		    *rel_csect = csect;
146884865Sobrien		    csect->flags |= SEC_RELOC;
146984865Sobrien		    ++csect->reloc_count;
147084865Sobrien		    ++relindx;
147184865Sobrien		    ++rel;
147284865Sobrien		    ++rel_csect;
147384865Sobrien		  }
147484865Sobrien	      }
147584865Sobrien
147684865Sobrien	    /* There are a number of other fields and section flags
147784865Sobrien	       which we do not bother to set.  */
147884865Sobrien
147984865Sobrien	    csect_index = ((esym
148084865Sobrien			    - (bfd_byte *) obj_coff_external_syms (abfd))
148184865Sobrien			   / symesz);
148284865Sobrien
148384865Sobrien	    xcoff_section_data (abfd, csect)->first_symndx = csect_index;
148484865Sobrien
148584865Sobrien	    if (first_csect == NULL)
148684865Sobrien	      first_csect = csect;
148784865Sobrien
148884865Sobrien	    /* If this symbol is C_EXT, we treat it as starting at the
148984865Sobrien	       beginning of the newly created section.  */
149084865Sobrien	    if (sym.n_sclass == C_EXT)
149184865Sobrien	      {
149284865Sobrien		section = csect;
149384865Sobrien		value = 0;
149484865Sobrien	      }
149584865Sobrien
149684865Sobrien	    /* If this is a TOC section for a symbol, record it.  */
149784865Sobrien	    if (set_toc != NULL)
149884865Sobrien	      set_toc->toc_section = csect;
149984865Sobrien	  }
150084865Sobrien	  break;
150184865Sobrien
150284865Sobrien	case XTY_LD:
150384865Sobrien	  /* This is a label definition.  The x_scnlen field is the
150494536Sobrien	     symbol index of the csect.  Usually the XTY_LD symbol will
150594536Sobrien	     follow its appropriate XTY_SD symbol.  The .set pseudo op can
150694536Sobrien	     cause the XTY_LD to not follow the XTY_SD symbol. */
150784865Sobrien	  {
1508130561Sobrien	    bfd_boolean bad;
150984865Sobrien
1510130561Sobrien	    bad = FALSE;
151184865Sobrien	    if (aux.x_csect.x_scnlen.l < 0
151284865Sobrien		|| (aux.x_csect.x_scnlen.l
151384865Sobrien		    >= esym - (bfd_byte *) obj_coff_external_syms (abfd)))
1514130561Sobrien	      bad = TRUE;
151584865Sobrien	    if (! bad)
151684865Sobrien	      {
151784865Sobrien		section = xcoff_data (abfd)->csects[aux.x_csect.x_scnlen.l];
151884865Sobrien		if (section == NULL
151984865Sobrien		    || (section->flags & SEC_HAS_CONTENTS) == 0)
1520130561Sobrien		  bad = TRUE;
152184865Sobrien	      }
152284865Sobrien	    if (bad)
152384865Sobrien	      {
152484865Sobrien		(*_bfd_error_handler)
1525218822Sdim		  (_("%B: misplaced XTY_LD `%s'"),
1526218822Sdim		   abfd, name);
152784865Sobrien		bfd_set_error (bfd_error_bad_value);
152884865Sobrien		goto error_return;
152984865Sobrien	      }
153094536Sobrien 	    csect = section;
153184865Sobrien	    value = sym.n_value - csect->vma;
153284865Sobrien	  }
153384865Sobrien	  break;
153484865Sobrien
153584865Sobrien	case XTY_CM:
153684865Sobrien	  /* This is an unitialized csect.  We could base the name on
1537130561Sobrien	     the storage mapping class, but we don't bother except for
1538130561Sobrien	     an XMC_TD symbol.  If this csect is externally visible,
1539130561Sobrien	     it is a common symbol.  We put XMC_TD symbols in sections
1540130561Sobrien	     named .tocbss, and rely on the linker script to put that
1541130561Sobrien	     in the TOC area.  */
154284865Sobrien
154384865Sobrien	  if (csect != NULL)
154484865Sobrien	    {
154584865Sobrien	      xcoff_section_data (abfd, csect)->last_symndx =
154684865Sobrien		((esym
154784865Sobrien		  - (bfd_byte *) obj_coff_external_syms (abfd))
154884865Sobrien		 / symesz);
154984865Sobrien	    }
155084865Sobrien
155184865Sobrien	  if (aux.x_csect.x_smclas == XMC_TD)
155294536Sobrien	    {
155394536Sobrien	      /* The linker script puts the .td section in the data
155494536Sobrien		 section after the .tc section.  */
1555218822Sdim	      csect = bfd_make_section_anyway_with_flags (abfd, ".td",
1556218822Sdim							  SEC_ALLOC);
155794536Sobrien	    }
155884865Sobrien	  else
1559218822Sdim	    csect = bfd_make_section_anyway_with_flags (abfd, ".bss",
1560218822Sdim							SEC_ALLOC);
1561218822Sdim
156284865Sobrien	  if (csect == NULL)
156384865Sobrien	    goto error_return;
156484865Sobrien	  csect->vma = sym.n_value;
1565218822Sdim	  csect->size = aux.x_csect.x_scnlen.l;
156684865Sobrien	  csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
156784865Sobrien	  /* There are a number of other fields and section flags
156884865Sobrien	     which we do not bother to set.  */
156984865Sobrien
157084865Sobrien	  csect_index = ((esym
157184865Sobrien			  - (bfd_byte *) obj_coff_external_syms (abfd))
157284865Sobrien			 / symesz);
157384865Sobrien
157494536Sobrien	  amt = sizeof (struct coff_section_tdata);
1575218822Sdim	  csect->used_by_bfd = bfd_zalloc (abfd, amt);
157684865Sobrien	  if (csect->used_by_bfd == NULL)
157784865Sobrien	    goto error_return;
157894536Sobrien	  amt = sizeof (struct xcoff_section_tdata);
157994536Sobrien	  coff_section_data (abfd, csect)->tdata = bfd_zalloc (abfd, amt);
158084865Sobrien	  if (coff_section_data (abfd, csect)->tdata == NULL)
158184865Sobrien	    goto error_return;
158284865Sobrien	  xcoff_section_data (abfd, csect)->first_symndx = csect_index;
158384865Sobrien
158484865Sobrien	  if (first_csect == NULL)
158584865Sobrien	    first_csect = csect;
158684865Sobrien
158784865Sobrien	  if (sym.n_sclass == C_EXT)
158884865Sobrien	    {
158984865Sobrien	      csect->flags |= SEC_IS_COMMON;
1590218822Sdim	      csect->size = 0;
159184865Sobrien	      section = csect;
159284865Sobrien	      value = aux.x_csect.x_scnlen.l;
159384865Sobrien	    }
159484865Sobrien
159584865Sobrien	  break;
159684865Sobrien	}
159784865Sobrien
159884865Sobrien      /* Check for magic symbol names.  */
159984865Sobrien      if ((smtyp == XTY_SD || smtyp == XTY_CM)
160084865Sobrien	  && aux.x_csect.x_smclas != XMC_TC
160184865Sobrien	  && aux.x_csect.x_smclas != XMC_TD)
160284865Sobrien	{
160394536Sobrien	  int i = -1;
160494536Sobrien
160584865Sobrien	  if (name[0] == '_')
160684865Sobrien	    {
160784865Sobrien	      if (strcmp (name, "_text") == 0)
160894536Sobrien		i = XCOFF_SPECIAL_SECTION_TEXT;
160984865Sobrien	      else if (strcmp (name, "_etext") == 0)
161094536Sobrien		i = XCOFF_SPECIAL_SECTION_ETEXT;
161184865Sobrien	      else if (strcmp (name, "_data") == 0)
161294536Sobrien		i = XCOFF_SPECIAL_SECTION_DATA;
161384865Sobrien	      else if (strcmp (name, "_edata") == 0)
161494536Sobrien		i = XCOFF_SPECIAL_SECTION_EDATA;
161584865Sobrien	      else if (strcmp (name, "_end") == 0)
161694536Sobrien		i = XCOFF_SPECIAL_SECTION_END;
161784865Sobrien	    }
161884865Sobrien	  else if (name[0] == 'e' && strcmp (name, "end") == 0)
1619218822Sdim	    i = XCOFF_SPECIAL_SECTION_END2;
162084865Sobrien
162184865Sobrien	  if (i != -1)
1622218822Sdim	    xcoff_hash_table (info)->special_sections[i] = csect;
162384865Sobrien	}
162484865Sobrien
162584865Sobrien      /* Now we have enough information to add the symbol to the
1626130561Sobrien	 linker hash table.  */
162784865Sobrien
162884865Sobrien      if (sym.n_sclass == C_EXT)
162984865Sobrien	{
1630130561Sobrien	  bfd_boolean copy;
163184865Sobrien
163284865Sobrien	  BFD_ASSERT (section != NULL);
163384865Sobrien
163484865Sobrien	  /* We must copy the name into memory if we got it from the
1635130561Sobrien	     syment itself, rather than the string table.  */
163684865Sobrien	  copy = default_copy;
163784865Sobrien	  if (sym._n._n_n._n_zeroes != 0
163884865Sobrien	      || sym._n._n_n._n_offset == 0)
1639130561Sobrien	    copy = TRUE;
164084865Sobrien
164184865Sobrien	  /* The AIX linker appears to only detect multiple symbol
164284865Sobrien	     definitions when there is a reference to the symbol.  If
164384865Sobrien	     a symbol is defined multiple times, and the only
164484865Sobrien	     references are from the same object file, the AIX linker
164584865Sobrien	     appears to permit it.  It does not merge the different
164684865Sobrien	     definitions, but handles them independently.  On the
164784865Sobrien	     other hand, if there is a reference, the linker reports
164884865Sobrien	     an error.
164984865Sobrien
165084865Sobrien	     This matters because the AIX <net/net_globals.h> header
165184865Sobrien	     file actually defines an initialized array, so we have to
165284865Sobrien	     actually permit that to work.
165384865Sobrien
165484865Sobrien	     Just to make matters even more confusing, the AIX linker
165584865Sobrien	     appears to permit multiple symbol definitions whenever
165684865Sobrien	     the second definition is in an archive rather than an
165784865Sobrien	     object file.  This may be a consequence of the manner in
165884865Sobrien	     which it handles archives: I think it may load the entire
165984865Sobrien	     archive in as separate csects, and then let garbage
166084865Sobrien	     collection discard symbols.
166184865Sobrien
166284865Sobrien	     We also have to handle the case of statically linking a
166384865Sobrien	     shared object, which will cause symbol redefinitions,
166484865Sobrien	     although this is an easier case to detect.  */
166584865Sobrien
166694536Sobrien 	  if (info->hash->creator == abfd->xvec)
166784865Sobrien	    {
166884865Sobrien	      if (! bfd_is_und_section (section))
1669218822Sdim		*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
1670218822Sdim						    name, TRUE, copy, FALSE);
167184865Sobrien	      else
1672218822Sdim		/* Make a copy of the symbol name to prevent problems with
1673218822Sdim		   merging symbols.  */
1674218822Sdim		*sym_hash = ((struct xcoff_link_hash_entry *)
1675218822Sdim			     bfd_wrapped_link_hash_lookup (abfd, info, name,
1676218822Sdim							   TRUE, TRUE, FALSE));
1677218822Sdim
167884865Sobrien	      if (*sym_hash == NULL)
167984865Sobrien		goto error_return;
168084865Sobrien	      if (((*sym_hash)->root.type == bfd_link_hash_defined
168184865Sobrien		   || (*sym_hash)->root.type == bfd_link_hash_defweak)
168284865Sobrien		  && ! bfd_is_und_section (section)
168384865Sobrien		  && ! bfd_is_com_section (section))
168484865Sobrien		{
168584865Sobrien		  /* This is a second definition of a defined symbol.  */
168684865Sobrien		  if ((abfd->flags & DYNAMIC) != 0
168784865Sobrien		      && ((*sym_hash)->smclas != XMC_GL
168884865Sobrien			  || aux.x_csect.x_smclas == XMC_GL
168984865Sobrien			  || ((*sym_hash)->root.u.def.section->owner->flags
169084865Sobrien			      & DYNAMIC) == 0))
169184865Sobrien		    {
169284865Sobrien		      /* The new symbol is from a shared library, and
1693130561Sobrien			 either the existing symbol is not global
1694130561Sobrien			 linkage code or this symbol is global linkage
1695130561Sobrien			 code.  If the existing symbol is global
1696130561Sobrien			 linkage code and the new symbol is not, then
1697130561Sobrien			 we want to use the new symbol.  */
169884865Sobrien		      section = bfd_und_section_ptr;
169984865Sobrien		      value = 0;
170084865Sobrien		    }
170184865Sobrien		  else if (((*sym_hash)->root.u.def.section->owner->flags
170284865Sobrien			    & DYNAMIC) != 0)
170384865Sobrien		    {
170484865Sobrien		      /* The existing symbol is from a shared library.
1705130561Sobrien			 Replace it.  */
170684865Sobrien		      (*sym_hash)->root.type = bfd_link_hash_undefined;
170784865Sobrien		      (*sym_hash)->root.u.undef.abfd =
170884865Sobrien			(*sym_hash)->root.u.def.section->owner;
170984865Sobrien		    }
171084865Sobrien		  else if (abfd->my_archive != NULL)
171184865Sobrien		    {
171284865Sobrien		      /* This is a redefinition in an object contained
1713130561Sobrien			 in an archive.  Just ignore it.  See the
1714130561Sobrien			 comment above.  */
171584865Sobrien		      section = bfd_und_section_ptr;
171684865Sobrien		      value = 0;
171784865Sobrien		    }
1718218822Sdim		  else if ((*sym_hash)->root.u.undef.next != NULL
171984865Sobrien			   || info->hash->undefs_tail == &(*sym_hash)->root)
172084865Sobrien		    {
172184865Sobrien		      /* This symbol has been referenced.  In this
1722130561Sobrien			 case, we just continue and permit the
1723130561Sobrien			 multiple definition error.  See the comment
1724130561Sobrien			 above about the behaviour of the AIX linker.  */
172584865Sobrien		    }
172684865Sobrien		  else if ((*sym_hash)->smclas == aux.x_csect.x_smclas)
172784865Sobrien		    {
172884865Sobrien		      /* The symbols are both csects of the same
1729130561Sobrien			 class.  There is at least a chance that this
1730130561Sobrien			 is a semi-legitimate redefinition.  */
173184865Sobrien		      section = bfd_und_section_ptr;
173284865Sobrien		      value = 0;
173384865Sobrien		      (*sym_hash)->flags |= XCOFF_MULTIPLY_DEFINED;
173484865Sobrien		    }
173584865Sobrien		}
173684865Sobrien	      else if (((*sym_hash)->flags & XCOFF_MULTIPLY_DEFINED) != 0
173784865Sobrien		       && ((*sym_hash)->root.type == bfd_link_hash_defined
173884865Sobrien			   || (*sym_hash)->root.type == bfd_link_hash_defweak)
173984865Sobrien		       && (bfd_is_und_section (section)
174084865Sobrien			   || bfd_is_com_section (section)))
174184865Sobrien		{
174284865Sobrien		  /* This is a reference to a multiply defined symbol.
174384865Sobrien		     Report the error now.  See the comment above
174484865Sobrien		     about the behaviour of the AIX linker.  We could
174584865Sobrien		     also do this with warning symbols, but I'm not
174684865Sobrien		     sure the XCOFF linker is wholly prepared to
174784865Sobrien		     handle them, and that would only be a warning,
174884865Sobrien		     not an error.  */
174984865Sobrien		  if (! ((*info->callbacks->multiple_definition)
175084865Sobrien			 (info, (*sym_hash)->root.root.string,
1751218822Sdim			  NULL, NULL, (bfd_vma) 0,
175284865Sobrien			  (*sym_hash)->root.u.def.section->owner,
175384865Sobrien			  (*sym_hash)->root.u.def.section,
175484865Sobrien			  (*sym_hash)->root.u.def.value)))
175584865Sobrien		    goto error_return;
175684865Sobrien		  /* Try not to give this error too many times.  */
175784865Sobrien		  (*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
175884865Sobrien		}
175984865Sobrien	    }
176084865Sobrien
176184865Sobrien	  /* _bfd_generic_link_add_one_symbol may call the linker to
176284865Sobrien	     generate an error message, and the linker may try to read
176384865Sobrien	     the symbol table to give a good error.  Right now, the
176484865Sobrien	     line numbers are in an inconsistent state, since they are
176584865Sobrien	     counted both in the real sections and in the new csects.
176684865Sobrien	     We need to leave the count in the real sections so that
176784865Sobrien	     the linker can report the line number of the error
176884865Sobrien	     correctly, so temporarily clobber the link to the csects
176984865Sobrien	     so that the linker will not try to read the line numbers
177084865Sobrien	     a second time from the csects.  */
177184865Sobrien	  BFD_ASSERT (last_real->next == first_csect);
177284865Sobrien	  last_real->next = NULL;
177384865Sobrien	  if (! (_bfd_generic_link_add_one_symbol
177484865Sobrien		 (info, abfd, name, flags, section, value,
1775218822Sdim		  NULL, copy, TRUE,
177684865Sobrien		  (struct bfd_link_hash_entry **) sym_hash)))
177784865Sobrien	    goto error_return;
177884865Sobrien	  last_real->next = first_csect;
177984865Sobrien
178084865Sobrien	  if (smtyp == XTY_CM)
178184865Sobrien	    {
178284865Sobrien	      if ((*sym_hash)->root.type != bfd_link_hash_common
178384865Sobrien		  || (*sym_hash)->root.u.c.p->section != csect)
1784218822Sdim		/* We don't need the common csect we just created.  */
1785218822Sdim		csect->size = 0;
178684865Sobrien	      else
1787218822Sdim		(*sym_hash)->root.u.c.p->alignment_power
1788218822Sdim		  = csect->alignment_power;
178984865Sobrien	    }
179084865Sobrien
179194536Sobrien 	  if (info->hash->creator == abfd->xvec)
179284865Sobrien	    {
179384865Sobrien	      int flag;
179484865Sobrien
179584865Sobrien	      if (smtyp == XTY_ER || smtyp == XTY_CM)
179684865Sobrien		flag = XCOFF_REF_REGULAR;
179784865Sobrien	      else
179884865Sobrien		flag = XCOFF_DEF_REGULAR;
179984865Sobrien	      (*sym_hash)->flags |= flag;
180084865Sobrien
180184865Sobrien	      if ((*sym_hash)->smclas == XMC_UA
180284865Sobrien		  || flag == XCOFF_DEF_REGULAR)
180384865Sobrien		(*sym_hash)->smclas = aux.x_csect.x_smclas;
180484865Sobrien	    }
180584865Sobrien	}
180684865Sobrien
180784865Sobrien      *csect_cache = csect;
180884865Sobrien
180984865Sobrien      esym += (sym.n_numaux + 1) * symesz;
181084865Sobrien      sym_hash += sym.n_numaux + 1;
181184865Sobrien      csect_cache += sym.n_numaux + 1;
181284865Sobrien    }
181384865Sobrien
181484865Sobrien  BFD_ASSERT (last_real == NULL || last_real->next == first_csect);
181584865Sobrien
181684865Sobrien  /* Make sure that we have seen all the relocs.  */
181784865Sobrien  for (o = abfd->sections; o != first_csect; o = o->next)
181884865Sobrien    {
181984865Sobrien      /* Reset the section size and the line number count, since the
182084865Sobrien	 data is now attached to the csects.  Don't reset the size of
182184865Sobrien	 the .debug section, since we need to read it below in
182284865Sobrien	 bfd_xcoff_size_dynamic_sections.  */
182384865Sobrien      if (strcmp (bfd_get_section_name (abfd, o), ".debug") != 0)
1824218822Sdim	o->size = 0;
182584865Sobrien      o->lineno_count = 0;
182684865Sobrien
182784865Sobrien      if ((o->flags & SEC_RELOC) != 0)
182884865Sobrien	{
182984865Sobrien	  bfd_size_type i;
183084865Sobrien	  struct internal_reloc *rel;
183184865Sobrien	  asection **rel_csect;
183284865Sobrien
183384865Sobrien	  rel = reloc_info[o->target_index].relocs;
183484865Sobrien	  rel_csect = reloc_info[o->target_index].csects;
183594536Sobrien
183684865Sobrien	  for (i = 0; i < o->reloc_count; i++, rel++, rel_csect++)
183784865Sobrien	    {
183884865Sobrien	      if (*rel_csect == NULL)
183984865Sobrien		{
184084865Sobrien		  (*_bfd_error_handler)
1841218822Sdim		    (_("%B: reloc %s:%d not in csect"),
1842218822Sdim		     abfd, o->name, i);
184384865Sobrien		  bfd_set_error (bfd_error_bad_value);
184484865Sobrien		  goto error_return;
184584865Sobrien		}
184684865Sobrien
184784865Sobrien	      /* We identify all symbols which are called, so that we
184884865Sobrien		 can create glue code for calls to functions imported
184984865Sobrien		 from dynamic objects.  */
185094536Sobrien 	      if (info->hash->creator == abfd->xvec
185184865Sobrien		  && *rel_csect != bfd_und_section_ptr
185284865Sobrien		  && (rel->r_type == R_BR
185384865Sobrien		      || rel->r_type == R_RBR)
185484865Sobrien		  && obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
185584865Sobrien		{
185684865Sobrien		  struct xcoff_link_hash_entry *h;
185784865Sobrien
185884865Sobrien		  h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
185984865Sobrien		  h->flags |= XCOFF_CALLED;
186084865Sobrien		  /* If the symbol name starts with a period, it is
1861130561Sobrien		     the code of a function.  If the symbol is
1862130561Sobrien		     currently undefined, then add an undefined symbol
1863130561Sobrien		     for the function descriptor.  This should do no
1864130561Sobrien		     harm, because any regular object that defines the
1865130561Sobrien		     function should also define the function
1866130561Sobrien		     descriptor.  It helps, because it means that we
1867130561Sobrien		     will identify the function descriptor with a
1868130561Sobrien		     dynamic object if a dynamic object defines it.  */
186984865Sobrien		  if (h->root.root.string[0] == '.'
187084865Sobrien		      && h->descriptor == NULL)
187184865Sobrien		    {
187284865Sobrien		      struct xcoff_link_hash_entry *hds;
1873107492Sobrien		      struct bfd_link_hash_entry *bh;
187484865Sobrien
187584865Sobrien		      hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
187684865Sobrien						    h->root.root.string + 1,
1877130561Sobrien						    TRUE, FALSE, TRUE);
187884865Sobrien		      if (hds == NULL)
187984865Sobrien			goto error_return;
188084865Sobrien		      if (hds->root.type == bfd_link_hash_new)
188184865Sobrien			{
1882107492Sobrien			  bh = &hds->root;
188384865Sobrien			  if (! (_bfd_generic_link_add_one_symbol
188484865Sobrien				 (info, abfd, hds->root.root.string,
188584865Sobrien				  (flagword) 0, bfd_und_section_ptr,
1886218822Sdim				  (bfd_vma) 0, NULL, FALSE,
1887130561Sobrien				  TRUE, &bh)))
188884865Sobrien			    goto error_return;
1889107492Sobrien			  hds = (struct xcoff_link_hash_entry *) bh;
189084865Sobrien			}
189184865Sobrien		      hds->flags |= XCOFF_DESCRIPTOR;
189284865Sobrien		      BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
189384865Sobrien				  && (h->flags & XCOFF_DESCRIPTOR) == 0);
189484865Sobrien		      hds->descriptor = h;
189584865Sobrien		      h->descriptor = hds;
189684865Sobrien		    }
189784865Sobrien		}
189884865Sobrien	    }
189984865Sobrien
190084865Sobrien	  free (reloc_info[o->target_index].csects);
190184865Sobrien	  reloc_info[o->target_index].csects = NULL;
190284865Sobrien
190384865Sobrien	  /* Reset SEC_RELOC and the reloc_count, since the reloc
190484865Sobrien	     information is now attached to the csects.  */
190594536Sobrien	  o->flags &=~ SEC_RELOC;
190684865Sobrien	  o->reloc_count = 0;
190784865Sobrien
190884865Sobrien	  /* If we are not keeping memory, free the reloc information.  */
190984865Sobrien	  if (! info->keep_memory
191084865Sobrien	      && coff_section_data (abfd, o) != NULL
191184865Sobrien	      && coff_section_data (abfd, o)->relocs != NULL
191284865Sobrien	      && ! coff_section_data (abfd, o)->keep_relocs)
191384865Sobrien	    {
191484865Sobrien	      free (coff_section_data (abfd, o)->relocs);
191584865Sobrien	      coff_section_data (abfd, o)->relocs = NULL;
191684865Sobrien	    }
191784865Sobrien	}
191884865Sobrien
191984865Sobrien      /* Free up the line numbers.  FIXME: We could cache these
1920130561Sobrien	 somewhere for the final link, to avoid reading them again.  */
192184865Sobrien      if (reloc_info[o->target_index].linenos != NULL)
192284865Sobrien	{
192384865Sobrien	  free (reloc_info[o->target_index].linenos);
192484865Sobrien	  reloc_info[o->target_index].linenos = NULL;
192584865Sobrien	}
192684865Sobrien    }
192784865Sobrien
192884865Sobrien  free (reloc_info);
192984865Sobrien
193084865Sobrien  obj_coff_keep_syms (abfd) = keep_syms;
193184865Sobrien
1932130561Sobrien  return TRUE;
193384865Sobrien
193484865Sobrien error_return:
193584865Sobrien  if (reloc_info != NULL)
193684865Sobrien    {
193784865Sobrien      for (o = abfd->sections; o != NULL; o = o->next)
193884865Sobrien	{
193984865Sobrien	  if (reloc_info[o->target_index].csects != NULL)
194084865Sobrien	    free (reloc_info[o->target_index].csects);
194184865Sobrien	  if (reloc_info[o->target_index].linenos != NULL)
194284865Sobrien	    free (reloc_info[o->target_index].linenos);
194384865Sobrien	}
194494536Sobrien      free (reloc_info);
194584865Sobrien    }
194684865Sobrien  obj_coff_keep_syms (abfd) = keep_syms;
1947130561Sobrien  return FALSE;
194884865Sobrien}
194984865Sobrien
195084865Sobrien#undef N_TMASK
195184865Sobrien#undef N_BTSHFT
195284865Sobrien
1953218822Sdim/* Add symbols from an XCOFF object file.  */
195484865Sobrien
1955130561Sobrienstatic bfd_boolean
1956218822Sdimxcoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
195784865Sobrien{
1958218822Sdim  if (! _bfd_coff_get_external_symbols (abfd))
1959218822Sdim    return FALSE;
1960218822Sdim  if (! xcoff_link_add_symbols (abfd, info))
1961218822Sdim    return FALSE;
1962218822Sdim  if (! info->keep_memory)
1963218822Sdim    {
1964218822Sdim      if (! _bfd_coff_free_symbols (abfd))
1965218822Sdim	return FALSE;
1966218822Sdim    }
1967218822Sdim  return TRUE;
1968218822Sdim}
1969218822Sdim
1970218822Sdim/* Look through the loader symbols to see if this dynamic object
1971218822Sdim   should be included in the link.  The native linker uses the loader
1972218822Sdim   symbols, not the normal symbol table, so we do too.  */
1973218822Sdim
1974218822Sdimstatic bfd_boolean
1975218822Sdimxcoff_link_check_dynamic_ar_symbols (bfd *abfd,
1976218822Sdim				     struct bfd_link_info *info,
1977218822Sdim				     bfd_boolean *pneeded)
1978218822Sdim{
197984865Sobrien  asection *lsec;
198094536Sobrien  bfd_byte *contents;
198184865Sobrien  struct internal_ldhdr ldhdr;
198284865Sobrien  const char *strings;
198394536Sobrien  bfd_byte *elsym, *elsymend;
198484865Sobrien
1985218822Sdim  *pneeded = FALSE;
198684865Sobrien
198784865Sobrien  lsec = bfd_get_section_by_name (abfd, ".loader");
198884865Sobrien  if (lsec == NULL)
1989218822Sdim    /* There are no symbols, so don't try to include it.  */
1990218822Sdim    return TRUE;
199184865Sobrien
199284865Sobrien  if (! xcoff_get_section_contents (abfd, lsec))
1993130561Sobrien    return FALSE;
199494536Sobrien  contents = coff_section_data (abfd, lsec)->contents;
199584865Sobrien
199694536Sobrien  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
199784865Sobrien
199894536Sobrien  strings = (char *) contents + ldhdr.l_stoff;
199984865Sobrien
2000218822Sdim  elsym = contents + bfd_xcoff_loader_symbol_offset (abfd, &ldhdr);
200194536Sobrien
2002218822Sdim  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz (abfd);
2003218822Sdim  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz (abfd))
200484865Sobrien    {
200584865Sobrien      struct internal_ldsym ldsym;
200684865Sobrien      char nambuf[SYMNMLEN + 1];
200784865Sobrien      const char *name;
2008218822Sdim      struct bfd_link_hash_entry *h;
200984865Sobrien
201094536Sobrien      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
201184865Sobrien
201284865Sobrien      /* We are only interested in exported symbols.  */
201384865Sobrien      if ((ldsym.l_smtype & L_EXPORT) == 0)
201484865Sobrien	continue;
201584865Sobrien
201684865Sobrien      if (ldsym._l._l_l._l_zeroes == 0)
201784865Sobrien	name = strings + ldsym._l._l_l._l_offset;
201884865Sobrien      else
201984865Sobrien	{
202084865Sobrien	  memcpy (nambuf, ldsym._l._l_name, SYMNMLEN);
202184865Sobrien	  nambuf[SYMNMLEN] = '\0';
202284865Sobrien	  name = nambuf;
202384865Sobrien	}
202484865Sobrien
2025218822Sdim      h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
2026218822Sdim
2027218822Sdim      /* We are only interested in symbols that are currently
2028218822Sdim	 undefined.  At this point we know that we are using an XCOFF
202984865Sobrien	 hash table.  */
2030218822Sdim      if (h != NULL
2031218822Sdim	  && h->type == bfd_link_hash_undefined
2032218822Sdim	  && (((struct xcoff_link_hash_entry *) h)->flags
2033218822Sdim	      & XCOFF_DEF_DYNAMIC) == 0)
2034218822Sdim	{
2035218822Sdim	  if (! (*info->callbacks->add_archive_element) (info, abfd, name))
2036218822Sdim	    return FALSE;
2037218822Sdim	  *pneeded = TRUE;
2038218822Sdim	  return TRUE;
2039218822Sdim	}
2040218822Sdim    }
204184865Sobrien
2042218822Sdim  /* We do not need this shared object.  */
2043218822Sdim  if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
2044218822Sdim    {
2045218822Sdim      free (coff_section_data (abfd, lsec)->contents);
2046218822Sdim      coff_section_data (abfd, lsec)->contents = NULL;
2047218822Sdim    }
204884865Sobrien
2049218822Sdim  return TRUE;
2050218822Sdim}
205184865Sobrien
2052218822Sdim/* Look through the symbols to see if this object file should be
2053218822Sdim   included in the link.  */
205484865Sobrien
2055218822Sdimstatic bfd_boolean
2056218822Sdimxcoff_link_check_ar_symbols (bfd *abfd,
2057218822Sdim			     struct bfd_link_info *info,
2058218822Sdim			     bfd_boolean *pneeded)
2059218822Sdim{
2060218822Sdim  bfd_size_type symesz;
2061218822Sdim  bfd_byte *esym;
2062218822Sdim  bfd_byte *esym_end;
206384865Sobrien
2064218822Sdim  *pneeded = FALSE;
206584865Sobrien
2066218822Sdim  if ((abfd->flags & DYNAMIC) != 0
2067218822Sdim      && ! info->static_link
2068218822Sdim      && info->hash->creator == abfd->xvec)
2069218822Sdim    return xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded);
207084865Sobrien
2071218822Sdim  symesz = bfd_coff_symesz (abfd);
2072218822Sdim  esym = (bfd_byte *) obj_coff_external_syms (abfd);
2073218822Sdim  esym_end = esym + obj_raw_syment_count (abfd) * symesz;
2074218822Sdim  while (esym < esym_end)
2075218822Sdim    {
2076218822Sdim      struct internal_syment sym;
207784865Sobrien
2078218822Sdim      bfd_coff_swap_sym_in (abfd, (void *) esym, (void *) &sym);
2079218822Sdim
2080218822Sdim      if (sym.n_sclass == C_EXT && sym.n_scnum != N_UNDEF)
208184865Sobrien	{
2082218822Sdim	  const char *name;
2083218822Sdim	  char buf[SYMNMLEN + 1];
2084218822Sdim	  struct bfd_link_hash_entry *h;
208584865Sobrien
2086218822Sdim	  /* This symbol is externally visible, and is defined by this
2087218822Sdim	     object file.  */
2088218822Sdim	  name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
208984865Sobrien
2090218822Sdim	  if (name == NULL)
2091218822Sdim	    return FALSE;
2092218822Sdim	  h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
209384865Sobrien
2094218822Sdim	  /* We are only interested in symbols that are currently
2095218822Sdim	     undefined.  If a symbol is currently known to be common,
2096218822Sdim	     XCOFF linkers do not bring in an object file which
2097218822Sdim	     defines it.  We also don't bring in symbols to satisfy
2098218822Sdim	     undefined references in shared objects.  */
2099218822Sdim	  if (h != NULL
2100218822Sdim	      && h->type == bfd_link_hash_undefined
2101218822Sdim 	      && (info->hash->creator != abfd->xvec
2102218822Sdim		  || (((struct xcoff_link_hash_entry *) h)->flags
2103218822Sdim		      & XCOFF_DEF_DYNAMIC) == 0))
210484865Sobrien	    {
2105218822Sdim	      if (! (*info->callbacks->add_archive_element) (info, abfd, name))
2106218822Sdim		return FALSE;
2107218822Sdim	      *pneeded = TRUE;
2108218822Sdim	      return TRUE;
210984865Sobrien	    }
211084865Sobrien	}
211184865Sobrien
2112218822Sdim      esym += (sym.n_numaux + 1) * symesz;
211384865Sobrien    }
211484865Sobrien
2115218822Sdim  /* We do not need this object file.  */
2116218822Sdim  return TRUE;
2117218822Sdim}
211884865Sobrien
2119218822Sdim/* Check a single archive element to see if we need to include it in
2120218822Sdim   the link.  *PNEEDED is set according to whether this element is
2121218822Sdim   needed in the link or not.  This is called via
2122218822Sdim   _bfd_generic_link_add_archive_symbols.  */
2123218822Sdim
2124218822Sdimstatic bfd_boolean
2125218822Sdimxcoff_link_check_archive_element (bfd *abfd,
2126218822Sdim				  struct bfd_link_info *info,
2127218822Sdim				  bfd_boolean *pneeded)
2128218822Sdim{
2129218822Sdim  if (! _bfd_coff_get_external_symbols (abfd))
2130130561Sobrien    return FALSE;
213184865Sobrien
2132218822Sdim  if (! xcoff_link_check_ar_symbols (abfd, info, pneeded))
2133218822Sdim    return FALSE;
2134218822Sdim
2135218822Sdim  if (*pneeded)
213684865Sobrien    {
2137218822Sdim      if (! xcoff_link_add_symbols (abfd, info))
2138218822Sdim	return FALSE;
213984865Sobrien    }
2140218822Sdim
2141218822Sdim  if (! info->keep_memory || ! *pneeded)
214284865Sobrien    {
2143218822Sdim      if (! _bfd_coff_free_symbols (abfd))
2144218822Sdim	return FALSE;
214584865Sobrien    }
214684865Sobrien
2147218822Sdim  return TRUE;
2148218822Sdim}
214984865Sobrien
2150218822Sdim/* Given an XCOFF BFD, add symbols to the global hash table as
2151218822Sdim   appropriate.  */
215284865Sobrien
2153218822Sdimbfd_boolean
2154218822Sdim_bfd_xcoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
2155218822Sdim{
2156218822Sdim  switch (bfd_get_format (abfd))
2157218822Sdim    {
2158218822Sdim    case bfd_object:
2159218822Sdim      return xcoff_link_add_object_symbols (abfd, info);
2160218822Sdim
2161218822Sdim    case bfd_archive:
2162218822Sdim      /* If the archive has a map, do the usual search.  We then need
2163218822Sdim	 to check the archive for dynamic objects, because they may not
2164218822Sdim	 appear in the archive map even though they should, perhaps, be
2165218822Sdim	 included.  If the archive has no map, we just consider each object
2166218822Sdim	 file in turn, since that apparently is what the AIX native linker
2167218822Sdim	 does.  */
2168218822Sdim      if (bfd_has_map (abfd))
2169218822Sdim	{
2170218822Sdim	  if (! (_bfd_generic_link_add_archive_symbols
2171218822Sdim		 (abfd, info, xcoff_link_check_archive_element)))
2172218822Sdim	    return FALSE;
2173218822Sdim	}
2174218822Sdim
2175218822Sdim      {
2176218822Sdim	bfd *member;
2177218822Sdim
2178218822Sdim	member = bfd_openr_next_archived_file (abfd, NULL);
2179218822Sdim	while (member != NULL)
2180218822Sdim	  {
2181218822Sdim	    if (bfd_check_format (member, bfd_object)
2182218822Sdim		&& (info->hash->creator == member->xvec)
2183218822Sdim		&& (! bfd_has_map (abfd) || (member->flags & DYNAMIC) != 0))
2184218822Sdim	      {
2185218822Sdim		bfd_boolean needed;
2186218822Sdim
2187218822Sdim		if (! xcoff_link_check_archive_element (member, info,
2188218822Sdim							&needed))
2189218822Sdim		  return FALSE;
2190218822Sdim		if (needed)
2191218822Sdim		  member->archive_pass = -1;
2192218822Sdim	      }
2193218822Sdim	    member = bfd_openr_next_archived_file (abfd, member);
2194218822Sdim	  }
2195218822Sdim      }
2196218822Sdim
2197218822Sdim      return TRUE;
2198218822Sdim
2199218822Sdim    default:
2200218822Sdim      bfd_set_error (bfd_error_wrong_format);
2201218822Sdim      return FALSE;
2202218822Sdim    }
220384865Sobrien}
220484865Sobrien
220584865Sobrien/* Mark a symbol as not being garbage, including the section in which
220684865Sobrien   it is defined.  */
220784865Sobrien
2208218822Sdimstatic inline bfd_boolean
2209218822Sdimxcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
221084865Sobrien{
221184865Sobrien  if ((h->flags & XCOFF_MARK) != 0)
2212130561Sobrien    return TRUE;
221384865Sobrien
221484865Sobrien  h->flags |= XCOFF_MARK;
221584865Sobrien  if (h->root.type == bfd_link_hash_defined
221684865Sobrien      || h->root.type == bfd_link_hash_defweak)
221784865Sobrien    {
221884865Sobrien      asection *hsec;
221984865Sobrien
222084865Sobrien      hsec = h->root.u.def.section;
222184865Sobrien      if (! bfd_is_abs_section (hsec)
222284865Sobrien	  && (hsec->flags & SEC_MARK) == 0)
222384865Sobrien	{
222484865Sobrien	  if (! xcoff_mark (info, hsec))
2225130561Sobrien	    return FALSE;
222684865Sobrien	}
222784865Sobrien    }
222884865Sobrien
222984865Sobrien  if (h->toc_section != NULL
223084865Sobrien      && (h->toc_section->flags & SEC_MARK) == 0)
223184865Sobrien    {
223284865Sobrien      if (! xcoff_mark (info, h->toc_section))
2233130561Sobrien	return FALSE;
223484865Sobrien    }
223584865Sobrien
2236130561Sobrien  return TRUE;
223784865Sobrien}
223884865Sobrien
223984865Sobrien/* The mark phase of garbage collection.  For a given section, mark
224084865Sobrien   it, and all the sections which define symbols to which it refers.
224184865Sobrien   Because this function needs to look at the relocs, we also count
224284865Sobrien   the number of relocs which need to be copied into the .loader
224384865Sobrien   section.  */
224484865Sobrien
2245130561Sobrienstatic bfd_boolean
2246218822Sdimxcoff_mark (struct bfd_link_info *info, asection *sec)
224784865Sobrien{
224884865Sobrien  if (bfd_is_abs_section (sec)
224984865Sobrien      || (sec->flags & SEC_MARK) != 0)
2250130561Sobrien    return TRUE;
225184865Sobrien
225284865Sobrien  sec->flags |= SEC_MARK;
225384865Sobrien
225484865Sobrien  if (sec->owner->xvec == info->hash->creator
225584865Sobrien      && coff_section_data (sec->owner, sec) != NULL
225684865Sobrien      && xcoff_section_data (sec->owner, sec) != NULL)
225784865Sobrien    {
2258218822Sdim      struct xcoff_link_hash_entry **hp, **hpend;
225984865Sobrien      struct internal_reloc *rel, *relend;
226084865Sobrien
226184865Sobrien      /* Mark all the symbols in this section.  */
226284865Sobrien      hp = (obj_xcoff_sym_hashes (sec->owner)
226384865Sobrien	    + xcoff_section_data (sec->owner, sec)->first_symndx);
226484865Sobrien      hpend = (obj_xcoff_sym_hashes (sec->owner)
226584865Sobrien	       + xcoff_section_data (sec->owner, sec)->last_symndx);
226684865Sobrien      for (; hp < hpend; hp++)
226784865Sobrien	{
2268218822Sdim	  struct xcoff_link_hash_entry *h;
226984865Sobrien
227084865Sobrien	  h = *hp;
227184865Sobrien	  if (h != NULL
227284865Sobrien	      && (h->flags & XCOFF_MARK) == 0)
227384865Sobrien	    {
227484865Sobrien	      if (! xcoff_mark_symbol (info, h))
2275130561Sobrien		return FALSE;
227684865Sobrien	    }
227784865Sobrien	}
227884865Sobrien
227984865Sobrien      /* Look through the section relocs.  */
228084865Sobrien      if ((sec->flags & SEC_RELOC) != 0
228184865Sobrien	  && sec->reloc_count > 0)
228284865Sobrien	{
2283130561Sobrien	  rel = xcoff_read_internal_relocs (sec->owner, sec, TRUE,
2284218822Sdim					    NULL, FALSE, NULL);
228584865Sobrien	  if (rel == NULL)
2286130561Sobrien	    return FALSE;
228784865Sobrien	  relend = rel + sec->reloc_count;
228884865Sobrien	  for (; rel < relend; rel++)
228984865Sobrien	    {
229084865Sobrien	      asection *rsec;
229184865Sobrien	      struct xcoff_link_hash_entry *h;
229284865Sobrien
229384865Sobrien	      if ((unsigned int) rel->r_symndx
229484865Sobrien		  > obj_raw_syment_count (sec->owner))
229584865Sobrien		continue;
229684865Sobrien
229784865Sobrien	      h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
229884865Sobrien	      if (h != NULL
229984865Sobrien		  && (h->flags & XCOFF_MARK) == 0)
230084865Sobrien		{
230184865Sobrien		  if (! xcoff_mark_symbol (info, h))
2302130561Sobrien		    return FALSE;
230384865Sobrien		}
230484865Sobrien
230584865Sobrien	      rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
230684865Sobrien	      if (rsec != NULL
230784865Sobrien		  && (rsec->flags & SEC_MARK) == 0)
230884865Sobrien		{
230984865Sobrien		  if (! xcoff_mark (info, rsec))
2310130561Sobrien		    return FALSE;
231184865Sobrien		}
231284865Sobrien
231384865Sobrien	      /* See if this reloc needs to be copied into the .loader
2314130561Sobrien		 section.  */
231584865Sobrien	      switch (rel->r_type)
231684865Sobrien		{
231784865Sobrien		default:
231884865Sobrien		  if (h == NULL
231984865Sobrien		      || h->root.type == bfd_link_hash_defined
232084865Sobrien		      || h->root.type == bfd_link_hash_defweak
232184865Sobrien		      || h->root.type == bfd_link_hash_common
232284865Sobrien		      || ((h->flags & XCOFF_CALLED) != 0
232384865Sobrien			  && (h->root.type == bfd_link_hash_undefined
232484865Sobrien			      || h->root.type == bfd_link_hash_undefweak)
232584865Sobrien			  && h->root.root.string[0] == '.'
232684865Sobrien			  && h->descriptor != NULL
232784865Sobrien			  && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
232884865Sobrien			      || ((h->descriptor->flags & XCOFF_IMPORT) != 0
232984865Sobrien				  && (h->descriptor->flags
233084865Sobrien				      & XCOFF_DEF_REGULAR) == 0))))
233184865Sobrien		    break;
233284865Sobrien		  /* Fall through.  */
233384865Sobrien		case R_POS:
233484865Sobrien		case R_NEG:
233584865Sobrien		case R_RL:
233684865Sobrien		case R_RLA:
233784865Sobrien		  ++xcoff_hash_table (info)->ldrel_count;
233884865Sobrien		  if (h != NULL)
233984865Sobrien		    h->flags |= XCOFF_LDREL;
234084865Sobrien		  break;
234184865Sobrien		case R_TOC:
234284865Sobrien		case R_GL:
234384865Sobrien		case R_TCL:
234484865Sobrien		case R_TRL:
234584865Sobrien		case R_TRLA:
234684865Sobrien		  /* We should never need a .loader reloc for a TOC
234784865Sobrien		     relative reloc.  */
234884865Sobrien		  break;
234984865Sobrien		}
235084865Sobrien	    }
235184865Sobrien
235284865Sobrien	  if (! info->keep_memory
235384865Sobrien	      && coff_section_data (sec->owner, sec) != NULL
235484865Sobrien	      && coff_section_data (sec->owner, sec)->relocs != NULL
235584865Sobrien	      && ! coff_section_data (sec->owner, sec)->keep_relocs)
235684865Sobrien	    {
235784865Sobrien	      free (coff_section_data (sec->owner, sec)->relocs);
235884865Sobrien	      coff_section_data (sec->owner, sec)->relocs = NULL;
235984865Sobrien	    }
236084865Sobrien	}
236184865Sobrien    }
236284865Sobrien
2363130561Sobrien  return TRUE;
236484865Sobrien}
236584865Sobrien
2366218822Sdim/* Routines that are called after all the input files have been
2367218822Sdim   handled, but before the sections are laid out in memory.  */
2368218822Sdim
236984865Sobrien/* The sweep phase of garbage collection.  Remove all garbage
237084865Sobrien   sections.  */
237184865Sobrien
237284865Sobrienstatic void
2373218822Sdimxcoff_sweep (struct bfd_link_info *info)
237484865Sobrien{
237584865Sobrien  bfd *sub;
237684865Sobrien
237784865Sobrien  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
237884865Sobrien    {
237984865Sobrien      asection *o;
238084865Sobrien
238184865Sobrien      for (o = sub->sections; o != NULL; o = o->next)
238284865Sobrien	{
238384865Sobrien	  if ((o->flags & SEC_MARK) == 0)
238484865Sobrien	    {
238584865Sobrien	      /* Keep all sections from non-XCOFF input files.  Keep
2386130561Sobrien		 special sections.  Keep .debug sections for the
2387130561Sobrien		 moment.  */
238884865Sobrien	      if (sub->xvec != info->hash->creator
238984865Sobrien		  || o == xcoff_hash_table (info)->debug_section
239084865Sobrien		  || o == xcoff_hash_table (info)->loader_section
239184865Sobrien		  || o == xcoff_hash_table (info)->linkage_section
239284865Sobrien		  || o == xcoff_hash_table (info)->toc_section
239384865Sobrien		  || o == xcoff_hash_table (info)->descriptor_section
239484865Sobrien		  || strcmp (o->name, ".debug") == 0)
239584865Sobrien		o->flags |= SEC_MARK;
239684865Sobrien	      else
239784865Sobrien		{
2398218822Sdim		  o->size = 0;
239984865Sobrien		  o->reloc_count = 0;
240084865Sobrien		  o->lineno_count = 0;
240184865Sobrien		}
240284865Sobrien	    }
240384865Sobrien	}
240484865Sobrien    }
240584865Sobrien}
240684865Sobrien
240784865Sobrien/* Record the number of elements in a set.  This is used to output the
240884865Sobrien   correct csect length.  */
240984865Sobrien
2410130561Sobrienbfd_boolean
2411218822Sdimbfd_xcoff_link_record_set (bfd *output_bfd,
2412218822Sdim			   struct bfd_link_info *info,
2413218822Sdim			   struct bfd_link_hash_entry *harg,
2414218822Sdim			   bfd_size_type size)
241584865Sobrien{
241684865Sobrien  struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
241784865Sobrien  struct xcoff_link_size_list *n;
241894536Sobrien  bfd_size_type amt;
241984865Sobrien
242084865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
2421130561Sobrien    return TRUE;
242284865Sobrien
242384865Sobrien  /* This will hardly ever be called.  I don't want to burn four bytes
242484865Sobrien     per global symbol, so instead the size is kept on a linked list
242584865Sobrien     attached to the hash table.  */
2426218822Sdim  amt = sizeof (* n);
2427218822Sdim  n = bfd_alloc (output_bfd, amt);
242884865Sobrien  if (n == NULL)
2429130561Sobrien    return FALSE;
243084865Sobrien  n->next = xcoff_hash_table (info)->size_list;
243184865Sobrien  n->h = h;
243284865Sobrien  n->size = size;
243384865Sobrien  xcoff_hash_table (info)->size_list = n;
243484865Sobrien
243584865Sobrien  h->flags |= XCOFF_HAS_SIZE;
243684865Sobrien
2437130561Sobrien  return TRUE;
243884865Sobrien}
243984865Sobrien
244084865Sobrien/* Import a symbol.  */
244184865Sobrien
2442130561Sobrienbfd_boolean
2443218822Sdimbfd_xcoff_import_symbol (bfd *output_bfd,
2444218822Sdim			 struct bfd_link_info *info,
2445218822Sdim			 struct bfd_link_hash_entry *harg,
2446218822Sdim			 bfd_vma val,
2447218822Sdim			 const char *imppath,
2448218822Sdim			 const char *impfile,
2449218822Sdim			 const char *impmember,
2450218822Sdim			 unsigned int syscall_flag)
245184865Sobrien{
245284865Sobrien  struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
245384865Sobrien
245484865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
2455130561Sobrien    return TRUE;
245684865Sobrien
245784865Sobrien  /* A symbol name which starts with a period is the code for a
245884865Sobrien     function.  If the symbol is undefined, then add an undefined
245984865Sobrien     symbol for the function descriptor, and import that instead.  */
246084865Sobrien  if (h->root.root.string[0] == '.'
246184865Sobrien      && h->root.type == bfd_link_hash_undefined
246284865Sobrien      && val == (bfd_vma) -1)
246384865Sobrien    {
246484865Sobrien      struct xcoff_link_hash_entry *hds;
246584865Sobrien
246684865Sobrien      hds = h->descriptor;
246784865Sobrien      if (hds == NULL)
246884865Sobrien	{
246984865Sobrien	  hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
247084865Sobrien					h->root.root.string + 1,
2471130561Sobrien					TRUE, FALSE, TRUE);
247284865Sobrien	  if (hds == NULL)
2473130561Sobrien	    return FALSE;
247484865Sobrien	  if (hds->root.type == bfd_link_hash_new)
247584865Sobrien	    {
247684865Sobrien	      hds->root.type = bfd_link_hash_undefined;
247784865Sobrien	      hds->root.u.undef.abfd = h->root.u.undef.abfd;
247884865Sobrien	    }
247984865Sobrien	  hds->flags |= XCOFF_DESCRIPTOR;
248084865Sobrien	  BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
248184865Sobrien		      && (h->flags & XCOFF_DESCRIPTOR) == 0);
248284865Sobrien	  hds->descriptor = h;
248384865Sobrien	  h->descriptor = hds;
248484865Sobrien	}
248584865Sobrien
248684865Sobrien      /* Now, if the descriptor is undefined, import the descriptor
2487130561Sobrien	 rather than the symbol we were told to import.  FIXME: Is
2488130561Sobrien	 this correct in all cases?  */
248984865Sobrien      if (hds->root.type == bfd_link_hash_undefined)
249084865Sobrien	h = hds;
249184865Sobrien    }
249284865Sobrien
249394536Sobrien  h->flags |= (XCOFF_IMPORT | syscall_flag);
249484865Sobrien
249584865Sobrien  if (val != (bfd_vma) -1)
249684865Sobrien    {
249784865Sobrien      if (h->root.type == bfd_link_hash_defined
249884865Sobrien	  && (! bfd_is_abs_section (h->root.u.def.section)
249984865Sobrien	      || h->root.u.def.value != val))
250084865Sobrien	{
250184865Sobrien	  if (! ((*info->callbacks->multiple_definition)
250284865Sobrien		 (info, h->root.root.string, h->root.u.def.section->owner,
250384865Sobrien		  h->root.u.def.section, h->root.u.def.value,
250484865Sobrien		  output_bfd, bfd_abs_section_ptr, val)))
2505130561Sobrien	    return FALSE;
250684865Sobrien	}
250784865Sobrien
250884865Sobrien      h->root.type = bfd_link_hash_defined;
250984865Sobrien      h->root.u.def.section = bfd_abs_section_ptr;
251084865Sobrien      h->root.u.def.value = val;
251184865Sobrien    }
251284865Sobrien
251384865Sobrien  /* We overload the ldindx field to hold the l_ifile value for this
251484865Sobrien     symbol.  */
251584865Sobrien  BFD_ASSERT (h->ldsym == NULL);
251684865Sobrien  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
251784865Sobrien  if (imppath == NULL)
251884865Sobrien    h->ldindx = -1;
251984865Sobrien  else
252084865Sobrien    {
252184865Sobrien      unsigned int c;
252284865Sobrien      struct xcoff_import_file **pp;
252384865Sobrien
252484865Sobrien      /* We start c at 1 because the first entry in the import list is
2525130561Sobrien	 reserved for the library search path.  */
252684865Sobrien      for (pp = &xcoff_hash_table (info)->imports, c = 1;
252784865Sobrien	   *pp != NULL;
252884865Sobrien	   pp = &(*pp)->next, ++c)
252984865Sobrien	{
253084865Sobrien	  if (strcmp ((*pp)->path, imppath) == 0
253184865Sobrien	      && strcmp ((*pp)->file, impfile) == 0
253284865Sobrien	      && strcmp ((*pp)->member, impmember) == 0)
253384865Sobrien	    break;
253484865Sobrien	}
253584865Sobrien
253684865Sobrien      if (*pp == NULL)
253784865Sobrien	{
253884865Sobrien	  struct xcoff_import_file *n;
2539218822Sdim	  bfd_size_type amt = sizeof (* n);
254084865Sobrien
2541218822Sdim	  n = bfd_alloc (output_bfd, amt);
254284865Sobrien	  if (n == NULL)
2543130561Sobrien	    return FALSE;
254484865Sobrien	  n->next = NULL;
254584865Sobrien	  n->path = imppath;
254684865Sobrien	  n->file = impfile;
254784865Sobrien	  n->member = impmember;
254884865Sobrien	  *pp = n;
254984865Sobrien	}
255084865Sobrien
255184865Sobrien      h->ldindx = c;
255284865Sobrien    }
255384865Sobrien
2554130561Sobrien  return TRUE;
255584865Sobrien}
255684865Sobrien
255784865Sobrien/* Export a symbol.  */
255884865Sobrien
2559130561Sobrienbfd_boolean
2560218822Sdimbfd_xcoff_export_symbol (bfd *output_bfd,
2561218822Sdim			 struct bfd_link_info *info,
2562218822Sdim			 struct bfd_link_hash_entry *harg)
256384865Sobrien{
256484865Sobrien  struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
256584865Sobrien
256684865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
2567130561Sobrien    return TRUE;
256884865Sobrien
256984865Sobrien  h->flags |= XCOFF_EXPORT;
257084865Sobrien
257184865Sobrien  /* FIXME: I'm not at all sure what syscall is supposed to mean, so
257284865Sobrien     I'm just going to ignore it until somebody explains it.  */
257384865Sobrien
257484865Sobrien  /* See if this is a function descriptor.  It may be one even though
257584865Sobrien     it is not so marked.  */
257684865Sobrien  if ((h->flags & XCOFF_DESCRIPTOR) == 0
257784865Sobrien      && h->root.root.string[0] != '.')
257884865Sobrien    {
257984865Sobrien      char *fnname;
258084865Sobrien      struct xcoff_link_hash_entry *hfn;
258194536Sobrien      bfd_size_type amt = strlen (h->root.root.string) + 2;
258284865Sobrien
2583218822Sdim      fnname = bfd_malloc (amt);
258484865Sobrien      if (fnname == NULL)
2585130561Sobrien	return FALSE;
258684865Sobrien      fnname[0] = '.';
258784865Sobrien      strcpy (fnname + 1, h->root.root.string);
258884865Sobrien      hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
2589130561Sobrien				    fnname, FALSE, FALSE, TRUE);
259084865Sobrien      free (fnname);
259184865Sobrien      if (hfn != NULL
259284865Sobrien	  && hfn->smclas == XMC_PR
259384865Sobrien	  && (hfn->root.type == bfd_link_hash_defined
259484865Sobrien	      || hfn->root.type == bfd_link_hash_defweak))
259584865Sobrien	{
259684865Sobrien	  h->flags |= XCOFF_DESCRIPTOR;
259784865Sobrien	  h->descriptor = hfn;
259884865Sobrien	  hfn->descriptor = h;
259984865Sobrien	}
260084865Sobrien    }
260184865Sobrien
260284865Sobrien  /* Make sure we don't garbage collect this symbol.  */
260384865Sobrien  if (! xcoff_mark_symbol (info, h))
2604130561Sobrien    return FALSE;
260584865Sobrien
260684865Sobrien  /* If this is a function descriptor, make sure we don't garbage
260784865Sobrien     collect the associated function code.  We normally don't have to
260884865Sobrien     worry about this, because the descriptor will be attached to a
260984865Sobrien     section with relocs, but if we are creating the descriptor
261084865Sobrien     ourselves those relocs will not be visible to the mark code.  */
261184865Sobrien  if ((h->flags & XCOFF_DESCRIPTOR) != 0)
261284865Sobrien    {
261384865Sobrien      if (! xcoff_mark_symbol (info, h->descriptor))
2614130561Sobrien	return FALSE;
261584865Sobrien    }
261684865Sobrien
2617130561Sobrien  return TRUE;
261884865Sobrien}
261984865Sobrien
262084865Sobrien/* Count a reloc against a symbol.  This is called for relocs
262184865Sobrien   generated by the linker script, typically for global constructors
262284865Sobrien   and destructors.  */
262384865Sobrien
2624130561Sobrienbfd_boolean
2625218822Sdimbfd_xcoff_link_count_reloc (bfd *output_bfd,
2626218822Sdim			    struct bfd_link_info *info,
2627218822Sdim			    const char *name)
262884865Sobrien{
262984865Sobrien  struct xcoff_link_hash_entry *h;
263084865Sobrien
263184865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
2632130561Sobrien    return TRUE;
263384865Sobrien
263484865Sobrien  h = ((struct xcoff_link_hash_entry *)
2635130561Sobrien       bfd_wrapped_link_hash_lookup (output_bfd, info, name, FALSE, FALSE,
2636130561Sobrien				     FALSE));
263784865Sobrien  if (h == NULL)
263884865Sobrien    {
263984865Sobrien      (*_bfd_error_handler) (_("%s: no such symbol"), name);
264084865Sobrien      bfd_set_error (bfd_error_no_symbols);
2641130561Sobrien      return FALSE;
264284865Sobrien    }
264384865Sobrien
264484865Sobrien  h->flags |= XCOFF_REF_REGULAR | XCOFF_LDREL;
264584865Sobrien  ++xcoff_hash_table (info)->ldrel_count;
264684865Sobrien
264784865Sobrien  /* Mark the symbol to avoid garbage collection.  */
264884865Sobrien  if (! xcoff_mark_symbol (info, h))
2649130561Sobrien    return FALSE;
265084865Sobrien
2651130561Sobrien  return TRUE;
265284865Sobrien}
265384865Sobrien
265484865Sobrien/* This function is called for each symbol to which the linker script
265584865Sobrien   assigns a value.  */
265684865Sobrien
2657130561Sobrienbfd_boolean
2658218822Sdimbfd_xcoff_record_link_assignment (bfd *output_bfd,
2659218822Sdim				  struct bfd_link_info *info,
2660218822Sdim				  const char *name)
266184865Sobrien{
266284865Sobrien  struct xcoff_link_hash_entry *h;
266384865Sobrien
266484865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
2665130561Sobrien    return TRUE;
266684865Sobrien
2667130561Sobrien  h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, TRUE, TRUE,
2668130561Sobrien			      FALSE);
266984865Sobrien  if (h == NULL)
2670130561Sobrien    return FALSE;
267184865Sobrien
267284865Sobrien  h->flags |= XCOFF_DEF_REGULAR;
267384865Sobrien
2674130561Sobrien  return TRUE;
267584865Sobrien}
267684865Sobrien
2677218822Sdim/* Add a symbol to the .loader symbols, if necessary.  */
2678218822Sdim
2679218822Sdimstatic bfd_boolean
2680218822Sdimxcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
2681218822Sdim{
2682218822Sdim  struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
2683218822Sdim  bfd_size_type amt;
2684218822Sdim
2685218822Sdim  if (h->root.type == bfd_link_hash_warning)
2686218822Sdim    h = (struct xcoff_link_hash_entry *) h->root.u.i.link;
2687218822Sdim
2688218822Sdim  /* __rtinit, this symbol has special handling. */
2689218822Sdim  if (h->flags & XCOFF_RTINIT)
2690218822Sdim      return TRUE;
2691218822Sdim
2692218822Sdim  /* If this is a final link, and the symbol was defined as a common
2693218822Sdim     symbol in a regular object file, and there was no definition in
2694218822Sdim     any dynamic object, then the linker will have allocated space for
2695218822Sdim     the symbol in a common section but the XCOFF_DEF_REGULAR flag
2696218822Sdim     will not have been set.  */
2697218822Sdim  if (h->root.type == bfd_link_hash_defined
2698218822Sdim      && (h->flags & XCOFF_DEF_REGULAR) == 0
2699218822Sdim      && (h->flags & XCOFF_REF_REGULAR) != 0
2700218822Sdim      && (h->flags & XCOFF_DEF_DYNAMIC) == 0
2701218822Sdim      && (bfd_is_abs_section (h->root.u.def.section)
2702218822Sdim	  || (h->root.u.def.section->owner->flags & DYNAMIC) == 0))
2703218822Sdim    h->flags |= XCOFF_DEF_REGULAR;
2704218822Sdim
2705218822Sdim  /* If all defined symbols should be exported, mark them now.  We
2706218822Sdim     don't want to export the actual functions, just the function
2707218822Sdim     descriptors.  */
2708218822Sdim  if (ldinfo->export_defineds
2709218822Sdim      && (h->flags & XCOFF_DEF_REGULAR) != 0
2710218822Sdim      && h->root.root.string[0] != '.')
2711218822Sdim    {
2712218822Sdim      bfd_boolean export;
2713218822Sdim
2714218822Sdim      /* We don't export a symbol which is being defined by an object
2715218822Sdim	 included from an archive which contains a shared object.  The
2716218822Sdim	 rationale is that if an archive contains both an unshared and
2717218822Sdim	 a shared object, then there must be some reason that the
2718218822Sdim	 unshared object is unshared, and we don't want to start
2719218822Sdim	 providing a shared version of it.  In particular, this solves
2720218822Sdim	 a bug involving the _savefNN set of functions.  gcc will call
2721218822Sdim	 those functions without providing a slot to restore the TOC,
2722218822Sdim	 so it is essential that these functions be linked in directly
2723218822Sdim	 and not from a shared object, which means that a shared
2724218822Sdim	 object which also happens to link them in must not export
2725218822Sdim	 them.  This is confusing, but I haven't been able to think of
2726218822Sdim	 a different approach.  Note that the symbols can, of course,
2727218822Sdim	 be exported explicitly.  */
2728218822Sdim      export = TRUE;
2729218822Sdim      if ((h->root.type == bfd_link_hash_defined
2730218822Sdim	   || h->root.type == bfd_link_hash_defweak)
2731218822Sdim	  && h->root.u.def.section->owner != NULL
2732218822Sdim	  && h->root.u.def.section->owner->my_archive != NULL)
2733218822Sdim	{
2734218822Sdim	  bfd *arbfd, *member;
2735218822Sdim
2736218822Sdim	  arbfd = h->root.u.def.section->owner->my_archive;
2737218822Sdim	  member = bfd_openr_next_archived_file (arbfd, NULL);
2738218822Sdim	  while (member != NULL)
2739218822Sdim	    {
2740218822Sdim	      if ((member->flags & DYNAMIC) != 0)
2741218822Sdim		{
2742218822Sdim		  export = FALSE;
2743218822Sdim		  break;
2744218822Sdim		}
2745218822Sdim	      member = bfd_openr_next_archived_file (arbfd, member);
2746218822Sdim	    }
2747218822Sdim	}
2748218822Sdim
2749218822Sdim      if (export)
2750218822Sdim	h->flags |= XCOFF_EXPORT;
2751218822Sdim    }
2752218822Sdim
2753218822Sdim  /* We don't want to garbage collect symbols which are not defined in
2754218822Sdim     XCOFF files.  This is a convenient place to mark them.  */
2755218822Sdim  if (xcoff_hash_table (ldinfo->info)->gc
2756218822Sdim      && (h->flags & XCOFF_MARK) == 0
2757218822Sdim      && (h->root.type == bfd_link_hash_defined
2758218822Sdim	  || h->root.type == bfd_link_hash_defweak)
2759218822Sdim      && (h->root.u.def.section->owner == NULL
2760218822Sdim	  || (h->root.u.def.section->owner->xvec
2761218822Sdim	      != ldinfo->info->hash->creator)))
2762218822Sdim    h->flags |= XCOFF_MARK;
2763218822Sdim
2764218822Sdim  /* If this symbol is called and defined in a dynamic object, or it
2765218822Sdim     is imported, then we need to set up global linkage code for it.
2766218822Sdim     (Unless we did garbage collection and we didn't need this
2767218822Sdim     symbol.)  */
2768218822Sdim  if ((h->flags & XCOFF_CALLED) != 0
2769218822Sdim      && (h->root.type == bfd_link_hash_undefined
2770218822Sdim	  || h->root.type == bfd_link_hash_undefweak)
2771218822Sdim      && h->root.root.string[0] == '.'
2772218822Sdim      && h->descriptor != NULL
2773218822Sdim      && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
2774218822Sdim	  || ((h->descriptor->flags & XCOFF_IMPORT) != 0
2775218822Sdim	      && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
2776218822Sdim      && (! xcoff_hash_table (ldinfo->info)->gc
2777218822Sdim	  || (h->flags & XCOFF_MARK) != 0))
2778218822Sdim    {
2779218822Sdim      asection *sec;
2780218822Sdim      struct xcoff_link_hash_entry *hds;
2781218822Sdim
2782218822Sdim      sec = xcoff_hash_table (ldinfo->info)->linkage_section;
2783218822Sdim      h->root.type = bfd_link_hash_defined;
2784218822Sdim      h->root.u.def.section = sec;
2785218822Sdim      h->root.u.def.value = sec->size;
2786218822Sdim      h->smclas = XMC_GL;
2787218822Sdim      h->flags |= XCOFF_DEF_REGULAR;
2788218822Sdim      sec->size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
2789218822Sdim
2790218822Sdim      /* The global linkage code requires a TOC entry for the
2791218822Sdim	 descriptor.  */
2792218822Sdim      hds = h->descriptor;
2793218822Sdim      BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
2794218822Sdim		   || hds->root.type == bfd_link_hash_undefweak)
2795218822Sdim		  && (hds->flags & XCOFF_DEF_REGULAR) == 0);
2796218822Sdim      hds->flags |= XCOFF_MARK;
2797218822Sdim      if (hds->toc_section == NULL)
2798218822Sdim	{
2799218822Sdim	  int byte_size;
2800218822Sdim
2801218822Sdim	  /* 32 vs 64
2802218822Sdim	     xcoff32 uses 4 bytes in the toc.
2803218822Sdim	     xcoff64 uses 8 bytes in the toc.  */
2804218822Sdim	  if (bfd_xcoff_is_xcoff64 (ldinfo->output_bfd))
2805218822Sdim	    byte_size = 8;
2806218822Sdim	  else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd))
2807218822Sdim	    byte_size = 4;
2808218822Sdim	  else
2809218822Sdim	    return FALSE;
2810218822Sdim
2811218822Sdim	  hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
2812218822Sdim	  hds->u.toc_offset = hds->toc_section->size;
2813218822Sdim	  hds->toc_section->size += byte_size;
2814218822Sdim	  ++xcoff_hash_table (ldinfo->info)->ldrel_count;
2815218822Sdim	  ++hds->toc_section->reloc_count;
2816218822Sdim	  hds->indx = -2;
2817218822Sdim	  hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
2818218822Sdim
2819218822Sdim	  /* We need to call xcoff_build_ldsyms recursively here,
2820218822Sdim	     because we may already have passed hds on the traversal.  */
2821218822Sdim	  xcoff_build_ldsyms (hds, p);
2822218822Sdim	}
2823218822Sdim    }
2824218822Sdim
2825218822Sdim  /* If this symbol is exported, but not defined, we need to try to
2826218822Sdim     define it.  */
2827218822Sdim  if ((h->flags & XCOFF_EXPORT) != 0
2828218822Sdim      && (h->flags & XCOFF_IMPORT) == 0
2829218822Sdim      && (h->flags & XCOFF_DEF_REGULAR) == 0
2830218822Sdim      && (h->flags & XCOFF_DEF_DYNAMIC) == 0
2831218822Sdim      && (h->root.type == bfd_link_hash_undefined
2832218822Sdim	  || h->root.type == bfd_link_hash_undefweak))
2833218822Sdim    {
2834218822Sdim      if ((h->flags & XCOFF_DESCRIPTOR) != 0
2835218822Sdim	  && (h->descriptor->root.type == bfd_link_hash_defined
2836218822Sdim	      || h->descriptor->root.type == bfd_link_hash_defweak))
2837218822Sdim	{
2838218822Sdim	  asection *sec;
2839218822Sdim
2840218822Sdim	  /* This is an undefined function descriptor associated with
2841218822Sdim	     a defined entry point.  We can build up a function
2842218822Sdim	     descriptor ourselves.  Believe it or not, the AIX linker
2843218822Sdim	     actually does this, and there are cases where we need to
2844218822Sdim	     do it as well.  */
2845218822Sdim	  sec = xcoff_hash_table (ldinfo->info)->descriptor_section;
2846218822Sdim	  h->root.type = bfd_link_hash_defined;
2847218822Sdim	  h->root.u.def.section = sec;
2848218822Sdim	  h->root.u.def.value = sec->size;
2849218822Sdim	  h->smclas = XMC_DS;
2850218822Sdim	  h->flags |= XCOFF_DEF_REGULAR;
2851218822Sdim
2852218822Sdim	  /* The size of the function descriptor depends if this is an
2853218822Sdim	     xcoff32 (12) or xcoff64 (24).  */
2854218822Sdim	  sec->size +=
2855218822Sdim	    bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
2856218822Sdim
2857218822Sdim	  /* A function descriptor uses two relocs: one for the
2858218822Sdim	     associated code, and one for the TOC address.  */
2859218822Sdim	  xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
2860218822Sdim	  sec->reloc_count += 2;
2861218822Sdim
2862218822Sdim	  /* We handle writing out the contents of the descriptor in
2863218822Sdim	     xcoff_write_global_symbol.  */
2864218822Sdim	}
2865218822Sdim      else
2866218822Sdim	{
2867218822Sdim	  (*_bfd_error_handler)
2868218822Sdim	    (_("warning: attempt to export undefined symbol `%s'"),
2869218822Sdim	     h->root.root.string);
2870218822Sdim	  h->ldsym = NULL;
2871218822Sdim	  return TRUE;
2872218822Sdim	}
2873218822Sdim    }
2874218822Sdim
2875218822Sdim  /* If this is still a common symbol, and it wasn't garbage
2876218822Sdim     collected, we need to actually allocate space for it in the .bss
2877218822Sdim     section.  */
2878218822Sdim  if (h->root.type == bfd_link_hash_common
2879218822Sdim      && (! xcoff_hash_table (ldinfo->info)->gc
2880218822Sdim	  || (h->flags & XCOFF_MARK) != 0)
2881218822Sdim      && h->root.u.c.p->section->size == 0)
2882218822Sdim    {
2883218822Sdim      BFD_ASSERT (bfd_is_com_section (h->root.u.c.p->section));
2884218822Sdim      h->root.u.c.p->section->size = h->root.u.c.size;
2885218822Sdim    }
2886218822Sdim
2887218822Sdim  /* We need to add a symbol to the .loader section if it is mentioned
2888218822Sdim     in a reloc which we are copying to the .loader section and it was
2889218822Sdim     not defined or common, or if it is the entry point, or if it is
2890218822Sdim     being exported.  */
2891218822Sdim
2892218822Sdim  if (((h->flags & XCOFF_LDREL) == 0
2893218822Sdim       || h->root.type == bfd_link_hash_defined
2894218822Sdim       || h->root.type == bfd_link_hash_defweak
2895218822Sdim       || h->root.type == bfd_link_hash_common)
2896218822Sdim      && (h->flags & XCOFF_ENTRY) == 0
2897218822Sdim      && (h->flags & XCOFF_EXPORT) == 0)
2898218822Sdim    {
2899218822Sdim      h->ldsym = NULL;
2900218822Sdim      return TRUE;
2901218822Sdim    }
2902218822Sdim
2903218822Sdim  /* We don't need to add this symbol if we did garbage collection and
2904218822Sdim     we did not mark this symbol.  */
2905218822Sdim  if (xcoff_hash_table (ldinfo->info)->gc
2906218822Sdim      && (h->flags & XCOFF_MARK) == 0)
2907218822Sdim    {
2908218822Sdim      h->ldsym = NULL;
2909218822Sdim      return TRUE;
2910218822Sdim    }
2911218822Sdim
2912218822Sdim  /* We may have already processed this symbol due to the recursive
2913218822Sdim     call above.  */
2914218822Sdim  if ((h->flags & XCOFF_BUILT_LDSYM) != 0)
2915218822Sdim    return TRUE;
2916218822Sdim
2917218822Sdim  /* We need to add this symbol to the .loader symbols.  */
2918218822Sdim
2919218822Sdim  BFD_ASSERT (h->ldsym == NULL);
2920218822Sdim  amt = sizeof (struct internal_ldsym);
2921218822Sdim  h->ldsym = bfd_zalloc (ldinfo->output_bfd, amt);
2922218822Sdim  if (h->ldsym == NULL)
2923218822Sdim    {
2924218822Sdim      ldinfo->failed = TRUE;
2925218822Sdim      return FALSE;
2926218822Sdim    }
2927218822Sdim
2928218822Sdim  if ((h->flags & XCOFF_IMPORT) != 0)
2929218822Sdim    h->ldsym->l_ifile = h->ldindx;
2930218822Sdim
2931218822Sdim  /* The first 3 symbol table indices are reserved to indicate the
2932218822Sdim     data, text and bss sections.  */
2933218822Sdim  h->ldindx = ldinfo->ldsym_count + 3;
2934218822Sdim
2935218822Sdim  ++ldinfo->ldsym_count;
2936218822Sdim
2937218822Sdim  if (! bfd_xcoff_put_ldsymbol_name (ldinfo->output_bfd, ldinfo,
2938218822Sdim				     h->ldsym, h->root.root.string))
2939218822Sdim    return FALSE;
2940218822Sdim
2941218822Sdim  h->flags |= XCOFF_BUILT_LDSYM;
2942218822Sdim
2943218822Sdim  return TRUE;
2944218822Sdim}
294584865Sobrien/* Build the .loader section.  This is called by the XCOFF linker
294684865Sobrien   emulation before_allocation routine.  We must set the size of the
294784865Sobrien   .loader section before the linker lays out the output file.
294884865Sobrien   LIBPATH is the library path to search for shared objects; this is
294984865Sobrien   normally built from the -L arguments passed to the linker.  ENTRY
295084865Sobrien   is the name of the entry point symbol (the -e linker option).
295184865Sobrien   FILE_ALIGN is the alignment to use for sections within the file
295284865Sobrien   (the -H linker option).  MAXSTACK is the maximum stack size (the
295384865Sobrien   -bmaxstack linker option).  MAXDATA is the maximum data size (the
295484865Sobrien   -bmaxdata linker option).  GC is whether to do garbage collection
295584865Sobrien   (the -bgc linker option).  MODTYPE is the module type (the
295684865Sobrien   -bmodtype linker option).  TEXTRO is whether the text section must
295784865Sobrien   be read only (the -btextro linker option).  EXPORT_DEFINEDS is
295884865Sobrien   whether all defined symbols should be exported (the -unix linker
295984865Sobrien   option).  SPECIAL_SECTIONS is set by this routine to csects with
296084865Sobrien   magic names like _end.  */
296184865Sobrien
2962130561Sobrienbfd_boolean
2963218822Sdimbfd_xcoff_size_dynamic_sections (bfd *output_bfd,
2964218822Sdim				 struct bfd_link_info *info,
2965218822Sdim				 const char *libpath,
2966218822Sdim				 const char *entry,
2967218822Sdim				 unsigned long file_align,
2968218822Sdim				 unsigned long maxstack,
2969218822Sdim				 unsigned long maxdata,
2970218822Sdim				 bfd_boolean gc,
2971218822Sdim				 int modtype,
2972218822Sdim				 bfd_boolean textro,
2973218822Sdim				 bfd_boolean export_defineds,
2974218822Sdim				 asection **special_sections,
2975218822Sdim				 bfd_boolean rtld)
297684865Sobrien{
297784865Sobrien  struct xcoff_link_hash_entry *hentry;
297884865Sobrien  asection *lsec;
297984865Sobrien  struct xcoff_loader_info ldinfo;
298084865Sobrien  int i;
298184865Sobrien  size_t impsize, impcount;
298284865Sobrien  struct xcoff_import_file *fl;
298384865Sobrien  struct internal_ldhdr *ldhdr;
298484865Sobrien  bfd_size_type stoff;
2985218822Sdim  char *out;
298684865Sobrien  asection *sec;
298784865Sobrien  bfd *sub;
298884865Sobrien  struct bfd_strtab_hash *debug_strtab;
298984865Sobrien  bfd_byte *debug_contents = NULL;
299094536Sobrien  bfd_size_type amt;
299184865Sobrien
299284865Sobrien  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
299384865Sobrien    {
299494536Sobrien      for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
299584865Sobrien	special_sections[i] = NULL;
2996130561Sobrien      return TRUE;
299784865Sobrien    }
299884865Sobrien
2999130561Sobrien  ldinfo.failed = FALSE;
300084865Sobrien  ldinfo.output_bfd = output_bfd;
300184865Sobrien  ldinfo.info = info;
300284865Sobrien  ldinfo.export_defineds = export_defineds;
300384865Sobrien  ldinfo.ldsym_count = 0;
300484865Sobrien  ldinfo.string_size = 0;
300584865Sobrien  ldinfo.strings = NULL;
300684865Sobrien  ldinfo.string_alc = 0;
300784865Sobrien
300884865Sobrien  xcoff_data (output_bfd)->maxstack = maxstack;
300984865Sobrien  xcoff_data (output_bfd)->maxdata = maxdata;
301084865Sobrien  xcoff_data (output_bfd)->modtype = modtype;
301184865Sobrien
301284865Sobrien  xcoff_hash_table (info)->file_align = file_align;
301384865Sobrien  xcoff_hash_table (info)->textro = textro;
301484865Sobrien
3015104834Sobrien  hentry = NULL;
3016104834Sobrien  if (entry != NULL)
301794536Sobrien    {
301884865Sobrien      hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
3019130561Sobrien				       FALSE, FALSE, TRUE);
302084865Sobrien      if (hentry != NULL)
302184865Sobrien	hentry->flags |= XCOFF_ENTRY;
302284865Sobrien    }
302384865Sobrien
302494536Sobrien  /* __rtinit */
3025130561Sobrien  if (info->init_function || info->fini_function || rtld)
3026104834Sobrien    {
3027104834Sobrien      struct xcoff_link_hash_entry *hsym;
3028104834Sobrien      struct internal_ldsym *ldsym;
3029130561Sobrien
3030104834Sobrien      hsym = xcoff_link_hash_lookup (xcoff_hash_table (info),
3031130561Sobrien				     "__rtinit", FALSE, FALSE, TRUE);
3032104834Sobrien      if (hsym == NULL)
3033104834Sobrien	{
3034104834Sobrien	  (*_bfd_error_handler)
3035104834Sobrien	    (_("error: undefined symbol __rtinit"));
3036130561Sobrien	  return FALSE;
3037104834Sobrien	}
3038130561Sobrien
3039104834Sobrien      xcoff_mark_symbol (info, hsym);
3040104834Sobrien      hsym->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
304194536Sobrien
3042218822Sdim      /* __rtinit initialized.  */
3043218822Sdim      amt = sizeof (* ldsym);
3044218822Sdim      ldsym = bfd_malloc (amt);
3045130561Sobrien
3046218822Sdim      ldsym->l_value = 0;		/* Will be filled in later.  */
3047218822Sdim      ldsym->l_scnum = 2;		/* Data section.  */
3048218822Sdim      ldsym->l_smtype = XTY_SD;		/* Csect section definition.  */
3049218822Sdim      ldsym->l_smclas = 5;		/* .rw.  */
3050218822Sdim      ldsym->l_ifile = 0;		/* Special system loader symbol.  */
3051218822Sdim      ldsym->l_parm = 0;		/* NA.  */
3052130561Sobrien
3053104834Sobrien      /* Force __rtinit to be the first symbol in the loader symbol table
3054104834Sobrien	 See xcoff_build_ldsyms
3055130561Sobrien
3056104834Sobrien	 The first 3 symbol table indices are reserved to indicate the data,
3057104834Sobrien	 text and bss sections.  */
3058104834Sobrien      BFD_ASSERT (0 == ldinfo.ldsym_count);
3059130561Sobrien
3060104834Sobrien      hsym->ldindx = 3;
3061104834Sobrien      ldinfo.ldsym_count = 1;
3062104834Sobrien      hsym->ldsym = ldsym;
3063130561Sobrien
3064130561Sobrien      if (! bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
3065130561Sobrien					 hsym->ldsym, hsym->root.root.string))
3066130561Sobrien	return FALSE;
3067130561Sobrien
3068104834Sobrien      /* This symbol is written out by xcoff_write_global_symbol
3069104834Sobrien	 Set stuff up so xcoff_write_global_symbol logic works.  */
3070104834Sobrien      hsym->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
3071104834Sobrien      hsym->root.type = bfd_link_hash_defined;
3072104834Sobrien      hsym->root.u.def.value = 0;
3073104834Sobrien    }
307494536Sobrien
307584865Sobrien  /* Garbage collect unused sections.  */
3076130561Sobrien  if (info->relocatable
307784865Sobrien      || ! gc
307884865Sobrien      || hentry == NULL
307984865Sobrien      || (hentry->root.type != bfd_link_hash_defined
308084865Sobrien	  && hentry->root.type != bfd_link_hash_defweak))
308184865Sobrien    {
3082130561Sobrien      gc = FALSE;
3083130561Sobrien      xcoff_hash_table (info)->gc = FALSE;
308484865Sobrien
308584865Sobrien      /* We still need to call xcoff_mark, in order to set ldrel_count
3086130561Sobrien	 correctly.  */
308784865Sobrien      for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
308884865Sobrien	{
308984865Sobrien	  asection *o;
309084865Sobrien
309184865Sobrien	  for (o = sub->sections; o != NULL; o = o->next)
309284865Sobrien	    {
309384865Sobrien	      if ((o->flags & SEC_MARK) == 0)
309484865Sobrien		{
309584865Sobrien		  if (! xcoff_mark (info, o))
309684865Sobrien		    goto error_return;
309784865Sobrien		}
309884865Sobrien	    }
309984865Sobrien	}
310084865Sobrien    }
310184865Sobrien  else
310284865Sobrien    {
310384865Sobrien      if (! xcoff_mark (info, hentry->root.u.def.section))
310484865Sobrien	goto error_return;
310584865Sobrien      xcoff_sweep (info);
3106130561Sobrien      xcoff_hash_table (info)->gc = TRUE;
310784865Sobrien    }
310884865Sobrien
310984865Sobrien  /* Return special sections to the caller.  */
311094536Sobrien  for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
311184865Sobrien    {
311294536Sobrien      sec = xcoff_hash_table (info)->special_sections[i];
311384865Sobrien
311484865Sobrien      if (sec != NULL
311584865Sobrien	  && gc
311684865Sobrien	  && (sec->flags & SEC_MARK) == 0)
3117218822Sdim	sec = NULL;
3118218822Sdim
311984865Sobrien      special_sections[i] = sec;
312084865Sobrien    }
312184865Sobrien
312284865Sobrien  if (info->input_bfds == NULL)
3123218822Sdim    /* I'm not sure what to do in this bizarre case.  */
3124218822Sdim    return TRUE;
312584865Sobrien
312684865Sobrien  xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
3127218822Sdim			    (void *) &ldinfo);
312884865Sobrien  if (ldinfo.failed)
312984865Sobrien    goto error_return;
313084865Sobrien
313184865Sobrien  /* Work out the size of the import file names.  Each import file ID
313284865Sobrien     consists of three null terminated strings: the path, the file
313384865Sobrien     name, and the archive member name.  The first entry in the list
313484865Sobrien     of names is the path to use to find objects, which the linker has
313584865Sobrien     passed in as the libpath argument.  For some reason, the path
313684865Sobrien     entry in the other import file names appears to always be empty.  */
313784865Sobrien  impsize = strlen (libpath) + 3;
313884865Sobrien  impcount = 1;
313984865Sobrien  for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
314084865Sobrien    {
314184865Sobrien      ++impcount;
314284865Sobrien      impsize += (strlen (fl->path)
314384865Sobrien		  + strlen (fl->file)
314484865Sobrien		  + strlen (fl->member)
314584865Sobrien		  + 3);
314684865Sobrien    }
314784865Sobrien
314884865Sobrien  /* Set up the .loader section header.  */
314984865Sobrien  ldhdr = &xcoff_hash_table (info)->ldhdr;
315094536Sobrien  ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
315184865Sobrien  ldhdr->l_nsyms = ldinfo.ldsym_count;
315284865Sobrien  ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
315384865Sobrien  ldhdr->l_istlen = impsize;
315484865Sobrien  ldhdr->l_nimpid = impcount;
315594536Sobrien  ldhdr->l_impoff = (bfd_xcoff_ldhdrsz(output_bfd)
315694536Sobrien		     + ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd)
315794536Sobrien		     + ldhdr->l_nreloc * bfd_xcoff_ldrelsz(output_bfd));
315884865Sobrien  ldhdr->l_stlen = ldinfo.string_size;
315984865Sobrien  stoff = ldhdr->l_impoff + impsize;
316084865Sobrien  if (ldinfo.string_size == 0)
316184865Sobrien    ldhdr->l_stoff = 0;
316284865Sobrien  else
316384865Sobrien    ldhdr->l_stoff = stoff;
316484865Sobrien
316594536Sobrien  /* 64 bit elements to ldhdr
316694536Sobrien     The swap out routine for 32 bit will ignore them.
316794536Sobrien     Nothing fancy, symbols come after the header and relocs come
316894536Sobrien     after symbols.  */
316994536Sobrien  ldhdr->l_symoff = bfd_xcoff_ldhdrsz (output_bfd);
317094536Sobrien  ldhdr->l_rldoff = (bfd_xcoff_ldhdrsz (output_bfd)
317194536Sobrien		     + ldhdr->l_nsyms * bfd_xcoff_ldsymsz (output_bfd));
317294536Sobrien
317384865Sobrien  /* We now know the final size of the .loader section.  Allocate
317484865Sobrien     space for it.  */
317584865Sobrien  lsec = xcoff_hash_table (info)->loader_section;
3176218822Sdim  lsec->size = stoff + ldhdr->l_stlen;
3177218822Sdim  lsec->contents = bfd_zalloc (output_bfd, lsec->size);
317884865Sobrien  if (lsec->contents == NULL)
317984865Sobrien    goto error_return;
318084865Sobrien
318184865Sobrien  /* Set up the header.  */
318294536Sobrien  bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
318384865Sobrien
318484865Sobrien  /* Set up the import file names.  */
318584865Sobrien  out = (char *) lsec->contents + ldhdr->l_impoff;
318684865Sobrien  strcpy (out, libpath);
318784865Sobrien  out += strlen (libpath) + 1;
318884865Sobrien  *out++ = '\0';
318984865Sobrien  *out++ = '\0';
319084865Sobrien  for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
319184865Sobrien    {
3192218822Sdim      const char *s;
319384865Sobrien
319484865Sobrien      s = fl->path;
319584865Sobrien      while ((*out++ = *s++) != '\0')
319684865Sobrien	;
319784865Sobrien      s = fl->file;
319884865Sobrien      while ((*out++ = *s++) != '\0')
319984865Sobrien	;
320084865Sobrien      s = fl->member;
320184865Sobrien      while ((*out++ = *s++) != '\0')
320284865Sobrien	;
320384865Sobrien    }
320484865Sobrien
320584865Sobrien  BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents) == stoff);
320684865Sobrien
320784865Sobrien  /* Set up the symbol string table.  */
320884865Sobrien  if (ldinfo.string_size > 0)
320984865Sobrien    {
321084865Sobrien      memcpy (out, ldinfo.strings, ldinfo.string_size);
321184865Sobrien      free (ldinfo.strings);
321284865Sobrien      ldinfo.strings = NULL;
321384865Sobrien    }
321484865Sobrien
321584865Sobrien  /* We can't set up the symbol table or the relocs yet, because we
321684865Sobrien     don't yet know the final position of the various sections.  The
321784865Sobrien     .loader symbols are written out when the corresponding normal
321884865Sobrien     symbols are written out in xcoff_link_input_bfd or
321984865Sobrien     xcoff_write_global_symbol.  The .loader relocs are written out
322084865Sobrien     when the corresponding normal relocs are handled in
3221218822Sdim     xcoff_link_input_bfd.  */
322284865Sobrien
322384865Sobrien  /* Allocate space for the magic sections.  */
322484865Sobrien  sec = xcoff_hash_table (info)->linkage_section;
3225218822Sdim  if (sec->size > 0)
322684865Sobrien    {
3227218822Sdim      sec->contents = bfd_zalloc (output_bfd, sec->size);
322884865Sobrien      if (sec->contents == NULL)
322984865Sobrien	goto error_return;
323084865Sobrien    }
323184865Sobrien  sec = xcoff_hash_table (info)->toc_section;
3232218822Sdim  if (sec->size > 0)
323384865Sobrien    {
3234218822Sdim      sec->contents = bfd_zalloc (output_bfd, sec->size);
323584865Sobrien      if (sec->contents == NULL)
323684865Sobrien	goto error_return;
323784865Sobrien    }
323884865Sobrien  sec = xcoff_hash_table (info)->descriptor_section;
3239218822Sdim  if (sec->size > 0)
324084865Sobrien    {
3241218822Sdim      sec->contents = bfd_zalloc (output_bfd, sec->size);
324284865Sobrien      if (sec->contents == NULL)
324384865Sobrien	goto error_return;
324484865Sobrien    }
324584865Sobrien
324684865Sobrien  /* Now that we've done garbage collection, figure out the contents
324784865Sobrien     of the .debug section.  */
324884865Sobrien  debug_strtab = xcoff_hash_table (info)->debug_strtab;
324984865Sobrien
325084865Sobrien  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
325184865Sobrien    {
325284865Sobrien      asection *subdeb;
325384865Sobrien      bfd_size_type symcount;
325484865Sobrien      unsigned long *debug_index;
325584865Sobrien      asection **csectpp;
325684865Sobrien      bfd_byte *esym, *esymend;
325784865Sobrien      bfd_size_type symesz;
325884865Sobrien
325984865Sobrien      if (sub->xvec != info->hash->creator)
326084865Sobrien	continue;
326184865Sobrien      subdeb = bfd_get_section_by_name (sub, ".debug");
3262218822Sdim      if (subdeb == NULL || subdeb->size == 0)
326384865Sobrien	continue;
326484865Sobrien
326584865Sobrien      if (info->strip == strip_all
326684865Sobrien	  || info->strip == strip_debugger
326784865Sobrien	  || info->discard == discard_all)
326884865Sobrien	{
3269218822Sdim	  subdeb->size = 0;
327084865Sobrien	  continue;
327184865Sobrien	}
327284865Sobrien
327384865Sobrien      if (! _bfd_coff_get_external_symbols (sub))
327484865Sobrien	goto error_return;
327584865Sobrien
327684865Sobrien      symcount = obj_raw_syment_count (sub);
3277218822Sdim      debug_index = bfd_zalloc (sub, symcount * sizeof (unsigned long));
327884865Sobrien      if (debug_index == NULL)
327984865Sobrien	goto error_return;
328084865Sobrien      xcoff_data (sub)->debug_indices = debug_index;
328184865Sobrien
328284865Sobrien      /* Grab the contents of the .debug section.  We use malloc and
328384865Sobrien	 copy the names into the debug stringtab, rather than
328484865Sobrien	 bfd_alloc, because I expect that, when linking many files
328584865Sobrien	 together, many of the strings will be the same.  Storing the
328684865Sobrien	 strings in the hash table should save space in this case.  */
3287218822Sdim      if (! bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
328884865Sobrien	goto error_return;
328984865Sobrien
329084865Sobrien      csectpp = xcoff_data (sub)->csects;
329184865Sobrien
3292104834Sobrien      /* Dynamic object do not have csectpp's.  */
3293130561Sobrien      if (NULL != csectpp)
329484865Sobrien	{
3295104834Sobrien	  symesz = bfd_coff_symesz (sub);
3296104834Sobrien	  esym = (bfd_byte *) obj_coff_external_syms (sub);
3297104834Sobrien	  esymend = esym + symcount * symesz;
329884865Sobrien
3299104834Sobrien	  while (esym < esymend)
3300104834Sobrien	    {
3301104834Sobrien	      struct internal_syment sym;
330284865Sobrien
3303218822Sdim	      bfd_coff_swap_sym_in (sub, (void *) esym, (void *) &sym);
330484865Sobrien
3305104834Sobrien	      *debug_index = (unsigned long) -1;
330684865Sobrien
3307104834Sobrien	      if (sym._n._n_n._n_zeroes == 0
3308104834Sobrien		  && *csectpp != NULL
3309104834Sobrien		  && (! gc
3310104834Sobrien		      || ((*csectpp)->flags & SEC_MARK) != 0
3311104834Sobrien		      || *csectpp == bfd_abs_section_ptr)
3312104834Sobrien		  && bfd_coff_symname_in_debug (sub, &sym))
3313104834Sobrien		{
3314104834Sobrien		  char *name;
3315104834Sobrien		  bfd_size_type indx;
3316104834Sobrien
3317104834Sobrien		  name = (char *) debug_contents + sym._n._n_n._n_offset;
3318130561Sobrien		  indx = _bfd_stringtab_add (debug_strtab, name, TRUE, TRUE);
3319104834Sobrien		  if (indx == (bfd_size_type) -1)
3320104834Sobrien		    goto error_return;
3321104834Sobrien		  *debug_index = indx;
3322104834Sobrien		}
3323104834Sobrien
3324104834Sobrien	      esym += (sym.n_numaux + 1) * symesz;
3325104834Sobrien	      csectpp += sym.n_numaux + 1;
3326104834Sobrien	      debug_index += sym.n_numaux + 1;
332784865Sobrien	    }
332884865Sobrien	}
332984865Sobrien
333084865Sobrien      free (debug_contents);
333184865Sobrien      debug_contents = NULL;
333284865Sobrien
333384865Sobrien      /* Clear the size of subdeb, so that it is not included directly
333484865Sobrien	 in the output file.  */
3335218822Sdim      subdeb->size = 0;
333684865Sobrien
333784865Sobrien      if (! info->keep_memory)
333884865Sobrien	{
333984865Sobrien	  if (! _bfd_coff_free_symbols (sub))
334084865Sobrien	    goto error_return;
334184865Sobrien	}
334284865Sobrien    }
334384865Sobrien
334484865Sobrien  if (info->strip != strip_all)
3345218822Sdim    xcoff_hash_table (info)->debug_section->size =
334684865Sobrien      _bfd_stringtab_size (debug_strtab);
334784865Sobrien
3348130561Sobrien  return TRUE;
334984865Sobrien
335084865Sobrien error_return:
335184865Sobrien  if (ldinfo.strings != NULL)
335284865Sobrien    free (ldinfo.strings);
335384865Sobrien  if (debug_contents != NULL)
335484865Sobrien    free (debug_contents);
3355130561Sobrien  return FALSE;
335684865Sobrien}
335784865Sobrien
3358130561Sobrienbfd_boolean
3359218822Sdimbfd_xcoff_link_generate_rtinit (bfd *abfd,
3360218822Sdim				const char *init,
3361218822Sdim				const char *fini,
3362218822Sdim				bfd_boolean rtld)
336394536Sobrien{
336494536Sobrien  struct bfd_in_memory *bim;
3365130561Sobrien
3366218822Sdim  bim = bfd_malloc ((bfd_size_type) sizeof (* bim));
336794536Sobrien  if (bim == NULL)
3368130561Sobrien    return FALSE;
336994536Sobrien
337094536Sobrien  bim->size = 0;
337194536Sobrien  bim->buffer = 0;
337294536Sobrien
337394536Sobrien  abfd->link_next = 0;
337494536Sobrien  abfd->format = bfd_object;
3375218822Sdim  abfd->iostream = (void *) bim;
337694536Sobrien  abfd->flags = BFD_IN_MEMORY;
337794536Sobrien  abfd->direction = write_direction;
337894536Sobrien  abfd->where = 0;
337994536Sobrien
3380130561Sobrien  if (! bfd_xcoff_generate_rtinit (abfd, init, fini, rtld))
3381130561Sobrien    return FALSE;
338294536Sobrien
338394536Sobrien  /* need to reset to unknown or it will not be read back in correctly */
338494536Sobrien  abfd->format = bfd_unknown;
338594536Sobrien  abfd->direction = read_direction;
338694536Sobrien  abfd->where = 0;
338794536Sobrien
3388130561Sobrien  return TRUE;
338994536Sobrien}
339084865Sobrien
339184865Sobrien/* Link an input file into the linker output file.  This function
339284865Sobrien   handles all the sections and relocations of the input file at once.  */
339384865Sobrien
3394130561Sobrienstatic bfd_boolean
3395218822Sdimxcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
3396218822Sdim		      bfd *input_bfd)
339784865Sobrien{
339884865Sobrien  bfd *output_bfd;
339984865Sobrien  const char *strings;
340084865Sobrien  bfd_size_type syment_base;
340184865Sobrien  unsigned int n_tmask;
340284865Sobrien  unsigned int n_btshft;
3403130561Sobrien  bfd_boolean copy, hash;
340484865Sobrien  bfd_size_type isymesz;
340584865Sobrien  bfd_size_type osymesz;
340684865Sobrien  bfd_size_type linesz;
340784865Sobrien  bfd_byte *esym;
340884865Sobrien  bfd_byte *esym_end;
340984865Sobrien  struct xcoff_link_hash_entry **sym_hash;
341084865Sobrien  struct internal_syment *isymp;
341184865Sobrien  asection **csectpp;
341284865Sobrien  unsigned long *debug_index;
341384865Sobrien  long *indexp;
341484865Sobrien  unsigned long output_index;
341584865Sobrien  bfd_byte *outsym;
341684865Sobrien  unsigned int incls;
341784865Sobrien  asection *oline;
3418130561Sobrien  bfd_boolean keep_syms;
341984865Sobrien  asection *o;
342084865Sobrien
342184865Sobrien  /* We can just skip DYNAMIC files, unless this is a static link.  */
342284865Sobrien  if ((input_bfd->flags & DYNAMIC) != 0
342384865Sobrien      && ! finfo->info->static_link)
3424130561Sobrien    return TRUE;
342584865Sobrien
342684865Sobrien  /* Move all the symbols to the output file.  */
342784865Sobrien  output_bfd = finfo->output_bfd;
342884865Sobrien  strings = NULL;
342984865Sobrien  syment_base = obj_raw_syment_count (output_bfd);
343084865Sobrien  isymesz = bfd_coff_symesz (input_bfd);
343184865Sobrien  osymesz = bfd_coff_symesz (output_bfd);
343284865Sobrien  linesz = bfd_coff_linesz (input_bfd);
343384865Sobrien  BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
343484865Sobrien
343584865Sobrien  n_tmask = coff_data (input_bfd)->local_n_tmask;
343684865Sobrien  n_btshft = coff_data (input_bfd)->local_n_btshft;
343784865Sobrien
343884865Sobrien  /* Define macros so that ISFCN, et. al., macros work correctly.  */
343984865Sobrien#define N_TMASK n_tmask
344084865Sobrien#define N_BTSHFT n_btshft
344184865Sobrien
3442130561Sobrien  copy = FALSE;
344384865Sobrien  if (! finfo->info->keep_memory)
3444130561Sobrien    copy = TRUE;
3445130561Sobrien  hash = TRUE;
344684865Sobrien  if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
3447130561Sobrien    hash = FALSE;
344884865Sobrien
344984865Sobrien  if (! _bfd_coff_get_external_symbols (input_bfd))
3450130561Sobrien    return FALSE;
345184865Sobrien
345284865Sobrien  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
345384865Sobrien  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
345484865Sobrien  sym_hash = obj_xcoff_sym_hashes (input_bfd);
345584865Sobrien  csectpp = xcoff_data (input_bfd)->csects;
345684865Sobrien  debug_index = xcoff_data (input_bfd)->debug_indices;
345784865Sobrien  isymp = finfo->internal_syms;
345884865Sobrien  indexp = finfo->sym_indices;
345984865Sobrien  output_index = syment_base;
346084865Sobrien  outsym = finfo->outsyms;
346184865Sobrien  incls = 0;
346284865Sobrien  oline = NULL;
346384865Sobrien
346484865Sobrien  while (esym < esym_end)
346584865Sobrien    {
346684865Sobrien      struct internal_syment isym;
346784865Sobrien      union internal_auxent aux;
346884865Sobrien      int smtyp = 0;
3469130561Sobrien      bfd_boolean skip;
3470130561Sobrien      bfd_boolean require;
347184865Sobrien      int add;
347284865Sobrien
3473218822Sdim      bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
347484865Sobrien
347584865Sobrien      /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
3476130561Sobrien	 information.  */
347784865Sobrien      if (isymp->n_sclass == C_EXT || isymp->n_sclass == C_HIDEXT)
347884865Sobrien	{
347984865Sobrien	  BFD_ASSERT (isymp->n_numaux > 0);
348084865Sobrien	  bfd_coff_swap_aux_in (input_bfd,
3481218822Sdim				(void *) (esym + isymesz * isymp->n_numaux),
348284865Sobrien				isymp->n_type, isymp->n_sclass,
348384865Sobrien				isymp->n_numaux - 1, isymp->n_numaux,
3484218822Sdim				(void *) &aux);
348594536Sobrien
348684865Sobrien	  smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
348784865Sobrien	}
348884865Sobrien
348984865Sobrien      /* Make a copy of *isymp so that the relocate_section function
349084865Sobrien	 always sees the original values.  This is more reliable than
349184865Sobrien	 always recomputing the symbol value even if we are stripping
349284865Sobrien	 the symbol.  */
349384865Sobrien      isym = *isymp;
349484865Sobrien
349584865Sobrien      /* If this symbol is in the .loader section, swap out the
3496130561Sobrien	 .loader symbol information.  If this is an external symbol
3497130561Sobrien	 reference to a defined symbol, though, then wait until we get
3498130561Sobrien	 to the definition.  */
349984865Sobrien      if (isym.n_sclass == C_EXT
350084865Sobrien	  && *sym_hash != NULL
350184865Sobrien	  && (*sym_hash)->ldsym != NULL
350284865Sobrien	  && (smtyp != XTY_ER
350384865Sobrien	      || (*sym_hash)->root.type == bfd_link_hash_undefined))
350484865Sobrien	{
350584865Sobrien	  struct xcoff_link_hash_entry *h;
350684865Sobrien	  struct internal_ldsym *ldsym;
350784865Sobrien
350884865Sobrien	  h = *sym_hash;
350984865Sobrien	  ldsym = h->ldsym;
351084865Sobrien	  if (isym.n_scnum > 0)
351184865Sobrien	    {
351284865Sobrien	      ldsym->l_scnum = (*csectpp)->output_section->target_index;
351384865Sobrien	      ldsym->l_value = (isym.n_value
351484865Sobrien				+ (*csectpp)->output_section->vma
351584865Sobrien				+ (*csectpp)->output_offset
351684865Sobrien				- (*csectpp)->vma);
351784865Sobrien	    }
351884865Sobrien	  else
351984865Sobrien	    {
352084865Sobrien	      ldsym->l_scnum = isym.n_scnum;
352184865Sobrien	      ldsym->l_value = isym.n_value;
352284865Sobrien	    }
352384865Sobrien
352484865Sobrien	  ldsym->l_smtype = smtyp;
352584865Sobrien	  if (((h->flags & XCOFF_DEF_REGULAR) == 0
352684865Sobrien	       && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
352784865Sobrien	      || (h->flags & XCOFF_IMPORT) != 0)
352884865Sobrien	    ldsym->l_smtype |= L_IMPORT;
352984865Sobrien	  if (((h->flags & XCOFF_DEF_REGULAR) != 0
353084865Sobrien	       && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
353184865Sobrien	      || (h->flags & XCOFF_EXPORT) != 0)
353284865Sobrien	    ldsym->l_smtype |= L_EXPORT;
353384865Sobrien	  if ((h->flags & XCOFF_ENTRY) != 0)
353484865Sobrien	    ldsym->l_smtype |= L_ENTRY;
353584865Sobrien
353684865Sobrien	  ldsym->l_smclas = aux.x_csect.x_smclas;
353784865Sobrien
353884865Sobrien	  if (ldsym->l_ifile == (bfd_size_type) -1)
353984865Sobrien	    ldsym->l_ifile = 0;
354084865Sobrien	  else if (ldsym->l_ifile == 0)
354184865Sobrien	    {
354284865Sobrien	      if ((ldsym->l_smtype & L_IMPORT) == 0)
354384865Sobrien		ldsym->l_ifile = 0;
354484865Sobrien	      else
354584865Sobrien		{
354684865Sobrien		  bfd *impbfd;
354784865Sobrien
354884865Sobrien		  if (h->root.type == bfd_link_hash_defined
354984865Sobrien		      || h->root.type == bfd_link_hash_defweak)
355084865Sobrien		    impbfd = h->root.u.def.section->owner;
355184865Sobrien		  else if (h->root.type == bfd_link_hash_undefined
355284865Sobrien			   || h->root.type == bfd_link_hash_undefweak)
355384865Sobrien		    impbfd = h->root.u.undef.abfd;
355484865Sobrien		  else
355584865Sobrien		    impbfd = NULL;
355684865Sobrien
355784865Sobrien		  if (impbfd == NULL)
355884865Sobrien		    ldsym->l_ifile = 0;
355984865Sobrien		  else
356084865Sobrien		    {
356184865Sobrien		      BFD_ASSERT (impbfd->xvec == finfo->output_bfd->xvec);
356284865Sobrien		      ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
356384865Sobrien		    }
356484865Sobrien		}
356584865Sobrien	    }
356684865Sobrien
356784865Sobrien	  ldsym->l_parm = 0;
356884865Sobrien
356984865Sobrien	  BFD_ASSERT (h->ldindx >= 0);
357094536Sobrien	  bfd_xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
357194536Sobrien				    (finfo->ldsym
357294536Sobrien				     + ((h->ldindx - 3)
357394536Sobrien					* bfd_xcoff_ldsymsz (finfo->output_bfd))));
357484865Sobrien	  h->ldsym = NULL;
357584865Sobrien
357684865Sobrien	  /* Fill in snentry now that we know the target_index.  */
357784865Sobrien	  if ((h->flags & XCOFF_ENTRY) != 0
357884865Sobrien	      && (h->root.type == bfd_link_hash_defined
357984865Sobrien		  || h->root.type == bfd_link_hash_defweak))
358094536Sobrien	    {
358194536Sobrien	      xcoff_data (output_bfd)->snentry =
358294536Sobrien		h->root.u.def.section->output_section->target_index;
358394536Sobrien	    }
358484865Sobrien	}
358584865Sobrien
358684865Sobrien      *indexp = -1;
358784865Sobrien
3588130561Sobrien      skip = FALSE;
3589130561Sobrien      require = FALSE;
359084865Sobrien      add = 1 + isym.n_numaux;
359184865Sobrien
359284865Sobrien      /* If we are skipping this csect, we want to skip this symbol.  */
359384865Sobrien      if (*csectpp == NULL)
3594130561Sobrien	skip = TRUE;
359584865Sobrien
359684865Sobrien      /* If we garbage collected this csect, we want to skip this
3597130561Sobrien	 symbol.  */
359884865Sobrien      if (! skip
359984865Sobrien	  && xcoff_hash_table (finfo->info)->gc
360084865Sobrien	  && ((*csectpp)->flags & SEC_MARK) == 0
360184865Sobrien	  && *csectpp != bfd_abs_section_ptr)
3602130561Sobrien	skip = TRUE;
360384865Sobrien
360484865Sobrien      /* An XCOFF linker always skips C_STAT symbols.  */
360584865Sobrien      if (! skip
360684865Sobrien	  && isymp->n_sclass == C_STAT)
3607130561Sobrien	skip = TRUE;
360884865Sobrien
360984865Sobrien      /* We skip all but the first TOC anchor.  */
361084865Sobrien      if (! skip
361184865Sobrien	  && isymp->n_sclass == C_HIDEXT
361284865Sobrien	  && aux.x_csect.x_smclas == XMC_TC0)
361384865Sobrien	{
361484865Sobrien	  if (finfo->toc_symindx != -1)
3615130561Sobrien	    skip = TRUE;
361684865Sobrien	  else
361784865Sobrien	    {
361884865Sobrien	      bfd_vma tocval, tocend;
361984865Sobrien	      bfd *inp;
362084865Sobrien
362184865Sobrien	      tocval = ((*csectpp)->output_section->vma
362284865Sobrien			+ (*csectpp)->output_offset
362384865Sobrien			+ isym.n_value
362484865Sobrien			- (*csectpp)->vma);
362584865Sobrien
362684865Sobrien	      /* We want to find out if tocval is a good value to use
3627130561Sobrien		 as the TOC anchor--that is, whether we can access all
3628130561Sobrien		 of the TOC using a 16 bit offset from tocval.  This
3629130561Sobrien		 test assumes that the TOC comes at the end of the
3630130561Sobrien		 output section, as it does in the default linker
3631130561Sobrien		 script.  */
363284865Sobrien	      tocend = ((*csectpp)->output_section->vma
3633218822Sdim			+ (*csectpp)->output_section->size);
363484865Sobrien	      for (inp = finfo->info->input_bfds;
363584865Sobrien		   inp != NULL;
363684865Sobrien		   inp = inp->link_next)
363784865Sobrien		{
363884865Sobrien
363984865Sobrien		  for (o = inp->sections; o != NULL; o = o->next)
364084865Sobrien		    if (strcmp (o->name, ".tocbss") == 0)
364184865Sobrien		      {
364284865Sobrien			bfd_vma new_toc_end;
364384865Sobrien			new_toc_end = (o->output_section->vma
364484865Sobrien				       + o->output_offset
3645218822Sdim				       + o->size);
364684865Sobrien			if (new_toc_end > tocend)
364784865Sobrien			  tocend = new_toc_end;
364884865Sobrien		      }
364984865Sobrien
365084865Sobrien		}
365184865Sobrien
365284865Sobrien	      if (tocval + 0x10000 < tocend)
365384865Sobrien		{
365484865Sobrien		  (*_bfd_error_handler)
365584865Sobrien		    (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"),
365684865Sobrien		     (unsigned long) (tocend - tocval));
365784865Sobrien		  bfd_set_error (bfd_error_file_too_big);
3658130561Sobrien		  return FALSE;
365984865Sobrien		}
366084865Sobrien
366184865Sobrien	      if (tocval + 0x8000 < tocend)
366284865Sobrien		{
366384865Sobrien		  bfd_vma tocadd;
366484865Sobrien
366584865Sobrien		  tocadd = tocend - (tocval + 0x8000);
366684865Sobrien		  tocval += tocadd;
366784865Sobrien		  isym.n_value += tocadd;
366884865Sobrien		}
366984865Sobrien
367084865Sobrien	      finfo->toc_symindx = output_index;
367184865Sobrien	      xcoff_data (finfo->output_bfd)->toc = tocval;
367284865Sobrien	      xcoff_data (finfo->output_bfd)->sntoc =
367384865Sobrien		(*csectpp)->output_section->target_index;
3674130561Sobrien	      require = TRUE;
367594536Sobrien
367684865Sobrien	    }
367784865Sobrien	}
367884865Sobrien
367984865Sobrien      /* If we are stripping all symbols, we want to skip this one.  */
368084865Sobrien      if (! skip
368184865Sobrien	  && finfo->info->strip == strip_all)
3682130561Sobrien	skip = TRUE;
368384865Sobrien
368484865Sobrien      /* We can skip resolved external references.  */
368584865Sobrien      if (! skip
368684865Sobrien	  && isym.n_sclass == C_EXT
368784865Sobrien	  && smtyp == XTY_ER
368884865Sobrien	  && (*sym_hash)->root.type != bfd_link_hash_undefined)
3689130561Sobrien	skip = TRUE;
369084865Sobrien
369184865Sobrien      /* We can skip common symbols if they got defined somewhere
3692130561Sobrien	 else.  */
369384865Sobrien      if (! skip
369484865Sobrien	  && isym.n_sclass == C_EXT
369584865Sobrien	  && smtyp == XTY_CM
369684865Sobrien	  && ((*sym_hash)->root.type != bfd_link_hash_common
369784865Sobrien	      || (*sym_hash)->root.u.c.p->section != *csectpp)
369884865Sobrien	  && ((*sym_hash)->root.type != bfd_link_hash_defined
369984865Sobrien	      || (*sym_hash)->root.u.def.section != *csectpp))
3700130561Sobrien	skip = TRUE;
370184865Sobrien
370284865Sobrien      /* Skip local symbols if we are discarding them.  */
370384865Sobrien      if (! skip
370484865Sobrien	  && finfo->info->discard == discard_all
370584865Sobrien	  && isym.n_sclass != C_EXT
370684865Sobrien	  && (isym.n_sclass != C_HIDEXT
370784865Sobrien	      || smtyp != XTY_SD))
3708130561Sobrien	skip = TRUE;
370984865Sobrien
371084865Sobrien      /* If we stripping debugging symbols, and this is a debugging
3711130561Sobrien	 symbol, then skip it.  */
371284865Sobrien      if (! skip
371384865Sobrien	  && finfo->info->strip == strip_debugger
371484865Sobrien	  && isym.n_scnum == N_DEBUG)
3715130561Sobrien	skip = TRUE;
371684865Sobrien
371784865Sobrien      /* If some symbols are stripped based on the name, work out the
371884865Sobrien	 name and decide whether to skip this symbol.  We don't handle
371984865Sobrien	 this correctly for symbols whose names are in the .debug
372084865Sobrien	 section; to get it right we would need a new bfd_strtab_hash
372184865Sobrien	 function to return the string given the index.  */
372284865Sobrien      if (! skip
372384865Sobrien	  && (finfo->info->strip == strip_some
372484865Sobrien	      || finfo->info->discard == discard_l)
372584865Sobrien	  && (debug_index == NULL || *debug_index == (unsigned long) -1))
372684865Sobrien	{
372784865Sobrien	  const char *name;
372884865Sobrien	  char buf[SYMNMLEN + 1];
372984865Sobrien
373084865Sobrien	  name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
373194536Sobrien
373284865Sobrien	  if (name == NULL)
3733130561Sobrien	    return FALSE;
373484865Sobrien
373584865Sobrien	  if ((finfo->info->strip == strip_some
3736130561Sobrien	       && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE,
3737130561Sobrien				    FALSE) == NULL))
373884865Sobrien	      || (finfo->info->discard == discard_l
373984865Sobrien		  && (isym.n_sclass != C_EXT
374084865Sobrien		      && (isym.n_sclass != C_HIDEXT
374184865Sobrien			  || smtyp != XTY_SD))
374284865Sobrien		  && bfd_is_local_label_name (input_bfd, name)))
3743130561Sobrien	    skip = TRUE;
374484865Sobrien	}
374584865Sobrien
374684865Sobrien      /* We can not skip the first TOC anchor.  */
374784865Sobrien      if (skip
374884865Sobrien	  && require
374984865Sobrien	  && finfo->info->strip != strip_all)
3750130561Sobrien	skip = FALSE;
375184865Sobrien
375284865Sobrien      /* We now know whether we are to skip this symbol or not.  */
375384865Sobrien      if (! skip)
375484865Sobrien	{
375584865Sobrien	  /* Adjust the symbol in order to output it.  */
375684865Sobrien
375784865Sobrien	  if (isym._n._n_n._n_zeroes == 0
375884865Sobrien	      && isym._n._n_n._n_offset != 0)
375984865Sobrien	    {
376084865Sobrien	      /* This symbol has a long name.  Enter it in the string
376184865Sobrien		 table we are building.  If *debug_index != -1, the
376284865Sobrien		 name has already been entered in the .debug section.  */
376384865Sobrien	      if (debug_index != NULL && *debug_index != (unsigned long) -1)
376484865Sobrien		isym._n._n_n._n_offset = *debug_index;
376584865Sobrien	      else
376684865Sobrien		{
376784865Sobrien		  const char *name;
376884865Sobrien		  bfd_size_type indx;
376984865Sobrien
3770218822Sdim		  name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
377194536Sobrien
377284865Sobrien		  if (name == NULL)
3773130561Sobrien		    return FALSE;
377484865Sobrien		  indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
377584865Sobrien		  if (indx == (bfd_size_type) -1)
3776130561Sobrien		    return FALSE;
377784865Sobrien		  isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
377884865Sobrien		}
377984865Sobrien	    }
378084865Sobrien
378184865Sobrien	  if (isym.n_sclass != C_BSTAT
378284865Sobrien	      && isym.n_sclass != C_ESTAT
378384865Sobrien	      && isym.n_sclass != C_DECL
378484865Sobrien	      && isym.n_scnum > 0)
378584865Sobrien	    {
378684865Sobrien	      isym.n_scnum = (*csectpp)->output_section->target_index;
378784865Sobrien	      isym.n_value += ((*csectpp)->output_section->vma
378884865Sobrien			       + (*csectpp)->output_offset
378984865Sobrien			       - (*csectpp)->vma);
379084865Sobrien	    }
379184865Sobrien
379284865Sobrien	  /* The value of a C_FILE symbol is the symbol index of the
379384865Sobrien	     next C_FILE symbol.  The value of the last C_FILE symbol
379484865Sobrien	     is -1.  We try to get this right, below, just before we
379584865Sobrien	     write the symbols out, but in the general case we may
379684865Sobrien	     have to write the symbol out twice.  */
379784865Sobrien	  if (isym.n_sclass == C_FILE)
379884865Sobrien	    {
379984865Sobrien	      if (finfo->last_file_index != -1
380094536Sobrien		  && finfo->last_file.n_value != (bfd_vma) output_index)
380184865Sobrien		{
380284865Sobrien		  /* We must correct the value of the last C_FILE entry.  */
380384865Sobrien		  finfo->last_file.n_value = output_index;
380484865Sobrien		  if ((bfd_size_type) finfo->last_file_index >= syment_base)
380584865Sobrien		    {
380684865Sobrien		      /* The last C_FILE symbol is in this input file.  */
380784865Sobrien		      bfd_coff_swap_sym_out (output_bfd,
3808218822Sdim					     (void *) &finfo->last_file,
3809218822Sdim					     (void *) (finfo->outsyms
381084865Sobrien						    + ((finfo->last_file_index
381184865Sobrien							- syment_base)
381284865Sobrien						       * osymesz)));
381384865Sobrien		    }
381484865Sobrien		  else
381584865Sobrien		    {
381684865Sobrien		      /* We have already written out the last C_FILE
381784865Sobrien			 symbol.  We need to write it out again.  We
381884865Sobrien			 borrow *outsym temporarily.  */
381994536Sobrien		      file_ptr pos;
382094536Sobrien
382184865Sobrien		      bfd_coff_swap_sym_out (output_bfd,
3822218822Sdim					     (void *) &finfo->last_file,
3823218822Sdim					     (void *) outsym);
382494536Sobrien
382594536Sobrien		      pos = obj_sym_filepos (output_bfd);
382694536Sobrien		      pos += finfo->last_file_index * osymesz;
382794536Sobrien		      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
382894536Sobrien			  || (bfd_bwrite (outsym, osymesz, output_bfd)
382984865Sobrien			      != osymesz))
3830130561Sobrien			return FALSE;
383184865Sobrien		    }
383284865Sobrien		}
383384865Sobrien
383484865Sobrien	      finfo->last_file_index = output_index;
383584865Sobrien	      finfo->last_file = isym;
383684865Sobrien	    }
383784865Sobrien
383884865Sobrien	  /* The value of a C_BINCL or C_EINCL symbol is a file offset
3839130561Sobrien	     into the line numbers.  We update the symbol values when
3840130561Sobrien	     we handle the line numbers.  */
384184865Sobrien	  if (isym.n_sclass == C_BINCL
384284865Sobrien	      || isym.n_sclass == C_EINCL)
384384865Sobrien	    {
384484865Sobrien	      isym.n_value = finfo->line_filepos;
384584865Sobrien	      ++incls;
384684865Sobrien	    }
384784865Sobrien
384884865Sobrien	  /* Output the symbol.  */
384984865Sobrien
3850218822Sdim	  bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
385184865Sobrien
385284865Sobrien	  *indexp = output_index;
385384865Sobrien
385484865Sobrien	  if (isym.n_sclass == C_EXT)
385584865Sobrien	    {
385684865Sobrien	      long indx;
385784865Sobrien	      struct xcoff_link_hash_entry *h;
385884865Sobrien
385984865Sobrien	      indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
386084865Sobrien		      / isymesz);
386184865Sobrien	      h = obj_xcoff_sym_hashes (input_bfd)[indx];
386284865Sobrien	      BFD_ASSERT (h != NULL);
386384865Sobrien	      h->indx = output_index;
386484865Sobrien	    }
386584865Sobrien
386684865Sobrien	  /* If this is a symbol in the TOC which we may have merged
3867130561Sobrien	     (class XMC_TC), remember the symbol index of the TOC
3868130561Sobrien	     symbol.  */
386984865Sobrien	  if (isym.n_sclass == C_HIDEXT
387084865Sobrien	      && aux.x_csect.x_smclas == XMC_TC
387184865Sobrien	      && *sym_hash != NULL)
387284865Sobrien	    {
387384865Sobrien	      BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
387484865Sobrien	      BFD_ASSERT ((*sym_hash)->toc_section != NULL);
387584865Sobrien	      (*sym_hash)->u.toc_indx = output_index;
387684865Sobrien	    }
387784865Sobrien
387884865Sobrien	  output_index += add;
387984865Sobrien	  outsym += add * osymesz;
388084865Sobrien	}
388184865Sobrien
388284865Sobrien      esym += add * isymesz;
388384865Sobrien      isymp += add;
388484865Sobrien      csectpp += add;
388584865Sobrien      sym_hash += add;
388684865Sobrien      if (debug_index != NULL)
388784865Sobrien	debug_index += add;
388884865Sobrien      ++indexp;
388984865Sobrien      for (--add; add > 0; --add)
389084865Sobrien	*indexp++ = -1;
389184865Sobrien    }
389284865Sobrien
389384865Sobrien  /* Fix up the aux entries and the C_BSTAT symbols.  This must be
389484865Sobrien     done in a separate pass, because we don't know the correct symbol
389584865Sobrien     indices until we have already decided which symbols we are going
389684865Sobrien     to keep.  */
389784865Sobrien
389884865Sobrien  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
389984865Sobrien  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
390084865Sobrien  isymp = finfo->internal_syms;
390184865Sobrien  indexp = finfo->sym_indices;
390284865Sobrien  csectpp = xcoff_data (input_bfd)->csects;
390384865Sobrien  outsym = finfo->outsyms;
390484865Sobrien  while (esym < esym_end)
390584865Sobrien    {
390684865Sobrien      int add;
390784865Sobrien
390884865Sobrien      add = 1 + isymp->n_numaux;
390984865Sobrien
391084865Sobrien      if (*indexp < 0)
391184865Sobrien	esym += add * isymesz;
391284865Sobrien      else
391384865Sobrien	{
391484865Sobrien	  int i;
391584865Sobrien
391684865Sobrien	  if (isymp->n_sclass == C_BSTAT)
391784865Sobrien	    {
391884865Sobrien	      struct internal_syment isym;
391984865Sobrien
392094536Sobrien	      bfd_vma indx;
392194536Sobrien
392284865Sobrien	      /* The value of a C_BSTAT symbol is the symbol table
3923130561Sobrien		 index of the containing csect.  */
3924218822Sdim	      bfd_coff_swap_sym_in (output_bfd, (void *) outsym, (void *) &isym);
392584865Sobrien	      indx = isym.n_value;
392684865Sobrien	      if (indx < obj_raw_syment_count (input_bfd))
392784865Sobrien		{
392884865Sobrien		  long symindx;
392984865Sobrien
393084865Sobrien		  symindx = finfo->sym_indices[indx];
393184865Sobrien		  if (symindx < 0)
393284865Sobrien		    isym.n_value = 0;
393384865Sobrien		  else
393484865Sobrien		    isym.n_value = symindx;
3935218822Sdim		  bfd_coff_swap_sym_out (output_bfd, (void *) &isym,
3936218822Sdim					 (void *) outsym);
393784865Sobrien		}
393884865Sobrien	    }
393984865Sobrien
394084865Sobrien	  esym += isymesz;
394184865Sobrien	  outsym += osymesz;
394284865Sobrien
394384865Sobrien	  for (i = 0; i < isymp->n_numaux && esym < esym_end; i++)
394484865Sobrien	    {
394584865Sobrien	      union internal_auxent aux;
394684865Sobrien
3947218822Sdim	      bfd_coff_swap_aux_in (input_bfd, (void *) esym, isymp->n_type,
394884865Sobrien				    isymp->n_sclass, i, isymp->n_numaux,
3949218822Sdim				    (void *) &aux);
395084865Sobrien
395184865Sobrien	      if (isymp->n_sclass == C_FILE)
395284865Sobrien		{
395384865Sobrien		  /* This is the file name (or some comment put in by
395484865Sobrien		     the compiler).  If it is long, we must put it in
395584865Sobrien		     the string table.  */
395684865Sobrien		  if (aux.x_file.x_n.x_zeroes == 0
395784865Sobrien		      && aux.x_file.x_n.x_offset != 0)
395884865Sobrien		    {
395984865Sobrien		      const char *filename;
396084865Sobrien		      bfd_size_type indx;
396184865Sobrien
396284865Sobrien		      BFD_ASSERT (aux.x_file.x_n.x_offset
396384865Sobrien				  >= STRING_SIZE_SIZE);
396484865Sobrien		      if (strings == NULL)
396584865Sobrien			{
396684865Sobrien			  strings = _bfd_coff_read_string_table (input_bfd);
396784865Sobrien			  if (strings == NULL)
3968130561Sobrien			    return FALSE;
396984865Sobrien			}
397084865Sobrien		      filename = strings + aux.x_file.x_n.x_offset;
397184865Sobrien		      indx = _bfd_stringtab_add (finfo->strtab, filename,
397284865Sobrien						 hash, copy);
397384865Sobrien		      if (indx == (bfd_size_type) -1)
3974130561Sobrien			return FALSE;
397584865Sobrien		      aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
397684865Sobrien		    }
397784865Sobrien		}
397884865Sobrien	      else if ((isymp->n_sclass == C_EXT
397984865Sobrien			|| isymp->n_sclass == C_HIDEXT)
398084865Sobrien		       && i + 1 == isymp->n_numaux)
398184865Sobrien		{
398294536Sobrien
398384865Sobrien		  /* We don't support type checking.  I don't know if
3984130561Sobrien		     anybody does.  */
398584865Sobrien		  aux.x_csect.x_parmhash = 0;
398684865Sobrien		  /* I don't think anybody uses these fields, but we'd
3987130561Sobrien		     better clobber them just in case.  */
398884865Sobrien		  aux.x_csect.x_stab = 0;
398984865Sobrien		  aux.x_csect.x_snstab = 0;
399094536Sobrien
399184865Sobrien		  if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
399284865Sobrien		    {
399384865Sobrien		      unsigned long indx;
399484865Sobrien
399584865Sobrien		      indx = aux.x_csect.x_scnlen.l;
399684865Sobrien		      if (indx < obj_raw_syment_count (input_bfd))
399784865Sobrien			{
399884865Sobrien			  long symindx;
399984865Sobrien
400084865Sobrien			  symindx = finfo->sym_indices[indx];
400184865Sobrien			  if (symindx < 0)
400294536Sobrien			    {
400394536Sobrien			      aux.x_csect.x_scnlen.l = 0;
400494536Sobrien			    }
400584865Sobrien			  else
400694536Sobrien			    {
400794536Sobrien			      aux.x_csect.x_scnlen.l = symindx;
400894536Sobrien			    }
400984865Sobrien			}
401084865Sobrien		    }
401184865Sobrien		}
401284865Sobrien	      else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
401384865Sobrien		{
401484865Sobrien		  unsigned long indx;
401584865Sobrien
401684865Sobrien		  if (ISFCN (isymp->n_type)
401784865Sobrien		      || ISTAG (isymp->n_sclass)
401884865Sobrien		      || isymp->n_sclass == C_BLOCK
401984865Sobrien		      || isymp->n_sclass == C_FCN)
402084865Sobrien		    {
402184865Sobrien		      indx = aux.x_sym.x_fcnary.x_fcn.x_endndx.l;
402284865Sobrien		      if (indx > 0
402384865Sobrien			  && indx < obj_raw_syment_count (input_bfd))
402484865Sobrien			{
402584865Sobrien			  /* We look forward through the symbol for
4026130561Sobrien			     the index of the next symbol we are going
4027130561Sobrien			     to include.  I don't know if this is
4028130561Sobrien			     entirely right.  */
402984865Sobrien			  while (finfo->sym_indices[indx] < 0
403084865Sobrien				 && indx < obj_raw_syment_count (input_bfd))
403184865Sobrien			    ++indx;
403284865Sobrien			  if (indx >= obj_raw_syment_count (input_bfd))
403384865Sobrien			    indx = output_index;
403484865Sobrien			  else
403584865Sobrien			    indx = finfo->sym_indices[indx];
403684865Sobrien			  aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
403794536Sobrien
403884865Sobrien			}
403984865Sobrien		    }
404084865Sobrien
404184865Sobrien		  indx = aux.x_sym.x_tagndx.l;
404284865Sobrien		  if (indx > 0 && indx < obj_raw_syment_count (input_bfd))
404384865Sobrien		    {
404484865Sobrien		      long symindx;
404584865Sobrien
404684865Sobrien		      symindx = finfo->sym_indices[indx];
404784865Sobrien		      if (symindx < 0)
404884865Sobrien			aux.x_sym.x_tagndx.l = 0;
404984865Sobrien		      else
405084865Sobrien			aux.x_sym.x_tagndx.l = symindx;
405184865Sobrien		    }
405294536Sobrien
405384865Sobrien		}
405484865Sobrien
405584865Sobrien	      /* Copy over the line numbers, unless we are stripping
405684865Sobrien		 them.  We do this on a symbol by symbol basis in
405784865Sobrien		 order to more easily handle garbage collection.  */
405884865Sobrien	      if ((isymp->n_sclass == C_EXT
405984865Sobrien		   || isymp->n_sclass == C_HIDEXT)
406084865Sobrien		  && i == 0
406184865Sobrien		  && isymp->n_numaux > 1
406284865Sobrien		  && ISFCN (isymp->n_type)
406384865Sobrien		  && aux.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
406484865Sobrien		{
406584865Sobrien		  if (finfo->info->strip != strip_none
406684865Sobrien		      && finfo->info->strip != strip_some)
406784865Sobrien		    aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
406884865Sobrien		  else
406984865Sobrien		    {
407084865Sobrien		      asection *enclosing;
407184865Sobrien		      unsigned int enc_count;
407294536Sobrien		      bfd_signed_vma linoff;
407384865Sobrien		      struct internal_lineno lin;
407484865Sobrien
407584865Sobrien		      o = *csectpp;
407684865Sobrien		      enclosing = xcoff_section_data (abfd, o)->enclosing;
407784865Sobrien		      enc_count = xcoff_section_data (abfd, o)->lineno_count;
407884865Sobrien		      if (oline != enclosing)
407984865Sobrien			{
408094536Sobrien			  file_ptr pos = enclosing->line_filepos;
408194536Sobrien			  bfd_size_type amt = linesz * enc_count;
408294536Sobrien			  if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
408394536Sobrien			      || (bfd_bread (finfo->linenos, amt, input_bfd)
408494536Sobrien				  != amt))
4085130561Sobrien			    return FALSE;
408684865Sobrien			  oline = enclosing;
408784865Sobrien			}
408884865Sobrien
408984865Sobrien		      linoff = (aux.x_sym.x_fcnary.x_fcn.x_lnnoptr
409084865Sobrien				- enclosing->line_filepos);
409184865Sobrien
409284865Sobrien		      bfd_coff_swap_lineno_in (input_bfd,
4093218822Sdim					       (void *) (finfo->linenos + linoff),
4094218822Sdim					       (void *) &lin);
409584865Sobrien		      if (lin.l_lnno != 0
409684865Sobrien			  || ((bfd_size_type) lin.l_addr.l_symndx
409784865Sobrien			      != ((esym
409884865Sobrien				   - isymesz
409984865Sobrien				   - ((bfd_byte *)
410084865Sobrien				      obj_coff_external_syms (input_bfd)))
410184865Sobrien				  / isymesz)))
410284865Sobrien			aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
410384865Sobrien		      else
410484865Sobrien			{
410584865Sobrien			  bfd_byte *linpend, *linp;
410684865Sobrien			  bfd_vma offset;
410784865Sobrien			  bfd_size_type count;
410884865Sobrien
410984865Sobrien			  lin.l_addr.l_symndx = *indexp;
4110218822Sdim			  bfd_coff_swap_lineno_out (output_bfd, (void *) &lin,
4111218822Sdim						    (void *) (finfo->linenos
411284865Sobrien							   + linoff));
411384865Sobrien
411484865Sobrien			  linpend = (finfo->linenos
411584865Sobrien				     + enc_count * linesz);
411684865Sobrien			  offset = (o->output_section->vma
411784865Sobrien				    + o->output_offset
411884865Sobrien				    - o->vma);
411984865Sobrien			  for (linp = finfo->linenos + linoff + linesz;
412084865Sobrien			       linp < linpend;
412184865Sobrien			       linp += linesz)
412284865Sobrien			    {
4123218822Sdim			      bfd_coff_swap_lineno_in (input_bfd, (void *) linp,
4124218822Sdim						       (void *) &lin);
412584865Sobrien			      if (lin.l_lnno == 0)
412684865Sobrien				break;
412784865Sobrien			      lin.l_addr.l_paddr += offset;
412884865Sobrien			      bfd_coff_swap_lineno_out (output_bfd,
4129218822Sdim							(void *) &lin,
4130218822Sdim							(void *) linp);
413184865Sobrien			    }
413284865Sobrien
413384865Sobrien			  count = (linp - (finfo->linenos + linoff)) / linesz;
413484865Sobrien
413584865Sobrien			  aux.x_sym.x_fcnary.x_fcn.x_lnnoptr =
413684865Sobrien			    (o->output_section->line_filepos
413784865Sobrien			     + o->output_section->lineno_count * linesz);
413884865Sobrien
413984865Sobrien			  if (bfd_seek (output_bfd,
414084865Sobrien					aux.x_sym.x_fcnary.x_fcn.x_lnnoptr,
414184865Sobrien					SEEK_SET) != 0
414294536Sobrien			      || (bfd_bwrite (finfo->linenos + linoff,
414394536Sobrien					     linesz * count, output_bfd)
414484865Sobrien				  != linesz * count))
4145130561Sobrien			    return FALSE;
414684865Sobrien
414784865Sobrien			  o->output_section->lineno_count += count;
414884865Sobrien
414984865Sobrien			  if (incls > 0)
415084865Sobrien			    {
415184865Sobrien			      struct internal_syment *iisp, *iispend;
415284865Sobrien			      long *iindp;
415384865Sobrien			      bfd_byte *oos;
415484865Sobrien			      int iiadd;
415584865Sobrien
415684865Sobrien			      /* Update any C_BINCL or C_EINCL symbols
4157130561Sobrien				 that refer to a line number in the
4158130561Sobrien				 range we just output.  */
415984865Sobrien			      iisp = finfo->internal_syms;
416084865Sobrien			      iispend = (iisp
416184865Sobrien					 + obj_raw_syment_count (input_bfd));
416284865Sobrien			      iindp = finfo->sym_indices;
416384865Sobrien			      oos = finfo->outsyms;
416484865Sobrien			      while (iisp < iispend)
416584865Sobrien				{
416684865Sobrien				  if (*iindp >= 0
416784865Sobrien				      && (iisp->n_sclass == C_BINCL
416884865Sobrien					  || iisp->n_sclass == C_EINCL)
416984865Sobrien				      && ((bfd_size_type) iisp->n_value
417094536Sobrien					  >= (bfd_size_type)(enclosing->line_filepos + linoff))
417184865Sobrien				      && ((bfd_size_type) iisp->n_value
417284865Sobrien					  < (enclosing->line_filepos
417384865Sobrien					     + enc_count * linesz)))
417484865Sobrien				    {
417584865Sobrien				      struct internal_syment iis;
417684865Sobrien
417784865Sobrien				      bfd_coff_swap_sym_in (output_bfd,
4178218822Sdim							    (void *) oos,
4179218822Sdim							    (void *) &iis);
418084865Sobrien				      iis.n_value =
418184865Sobrien					(iisp->n_value
418284865Sobrien					 - enclosing->line_filepos
418384865Sobrien					 - linoff
418484865Sobrien					 + aux.x_sym.x_fcnary.x_fcn.x_lnnoptr);
418584865Sobrien				      bfd_coff_swap_sym_out (output_bfd,
4186218822Sdim							     (void *) &iis,
4187218822Sdim							     (void *) oos);
418884865Sobrien				      --incls;
418984865Sobrien				    }
419084865Sobrien
419184865Sobrien				  iiadd = 1 + iisp->n_numaux;
419284865Sobrien				  if (*iindp >= 0)
419384865Sobrien				    oos += iiadd * osymesz;
419484865Sobrien				  iisp += iiadd;
419584865Sobrien				  iindp += iiadd;
419684865Sobrien				}
419784865Sobrien			    }
419884865Sobrien			}
419984865Sobrien		    }
420084865Sobrien		}
420184865Sobrien
4202218822Sdim	      bfd_coff_swap_aux_out (output_bfd, (void *) &aux, isymp->n_type,
420384865Sobrien				     isymp->n_sclass, i, isymp->n_numaux,
4204218822Sdim				     (void *) outsym);
420584865Sobrien	      outsym += osymesz;
420684865Sobrien	      esym += isymesz;
420784865Sobrien	    }
420884865Sobrien	}
420984865Sobrien
421084865Sobrien      indexp += add;
421184865Sobrien      isymp += add;
421284865Sobrien      csectpp += add;
421384865Sobrien    }
421484865Sobrien
421584865Sobrien  /* If we swapped out a C_FILE symbol, guess that the next C_FILE
421684865Sobrien     symbol will be the first symbol in the next input file.  In the
421784865Sobrien     normal case, this will save us from writing out the C_FILE symbol
421884865Sobrien     again.  */
421984865Sobrien  if (finfo->last_file_index != -1
422084865Sobrien      && (bfd_size_type) finfo->last_file_index >= syment_base)
422184865Sobrien    {
422284865Sobrien      finfo->last_file.n_value = output_index;
4223218822Sdim      bfd_coff_swap_sym_out (output_bfd, (void *) &finfo->last_file,
4224218822Sdim			     (void *) (finfo->outsyms
422584865Sobrien 				    + ((finfo->last_file_index - syment_base)
422684865Sobrien 				       * osymesz)));
422784865Sobrien    }
422884865Sobrien
422984865Sobrien  /* Write the modified symbols to the output file.  */
423084865Sobrien  if (outsym > finfo->outsyms)
423184865Sobrien    {
423294536Sobrien      file_ptr pos = obj_sym_filepos (output_bfd) + syment_base * osymesz;
423394536Sobrien      bfd_size_type amt = outsym - finfo->outsyms;
423494536Sobrien      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
423594536Sobrien	  || bfd_bwrite (finfo->outsyms, amt, output_bfd) != amt)
4236130561Sobrien	return FALSE;
423784865Sobrien
423884865Sobrien      BFD_ASSERT ((obj_raw_syment_count (output_bfd)
423984865Sobrien		   + (outsym - finfo->outsyms) / osymesz)
424084865Sobrien		  == output_index);
424184865Sobrien
424284865Sobrien      obj_raw_syment_count (output_bfd) = output_index;
424384865Sobrien    }
424484865Sobrien
424584865Sobrien  /* Don't let the linker relocation routines discard the symbols.  */
424684865Sobrien  keep_syms = obj_coff_keep_syms (input_bfd);
4247130561Sobrien  obj_coff_keep_syms (input_bfd) = TRUE;
424884865Sobrien
424984865Sobrien  /* Relocate the contents of each section.  */
425084865Sobrien  for (o = input_bfd->sections; o != NULL; o = o->next)
425184865Sobrien    {
425284865Sobrien      bfd_byte *contents;
425384865Sobrien
425484865Sobrien      if (! o->linker_mark)
4255218822Sdim	/* This section was omitted from the link.  */
4256218822Sdim	continue;
425784865Sobrien
425884865Sobrien      if ((o->flags & SEC_HAS_CONTENTS) == 0
4259218822Sdim	  || o->size == 0
426084865Sobrien	  || (o->flags & SEC_IN_MEMORY) != 0)
426184865Sobrien	continue;
426284865Sobrien
426384865Sobrien      /* We have set filepos correctly for the sections we created to
426494536Sobrien	 represent csects, so bfd_get_section_contents should work.  */
426584865Sobrien      if (coff_section_data (input_bfd, o) != NULL
426684865Sobrien	  && coff_section_data (input_bfd, o)->contents != NULL)
426784865Sobrien	contents = coff_section_data (input_bfd, o)->contents;
4268218822Sdim      else
4269218822Sdim	{
4270218822Sdim	  bfd_size_type sz = o->rawsize ? o->rawsize : o->size;
4271218822Sdim	  if (!bfd_get_section_contents (input_bfd, o, finfo->contents, 0, sz))
4272218822Sdim	    return FALSE;
4273218822Sdim	  contents = finfo->contents;
4274218822Sdim	}
427584865Sobrien
427684865Sobrien      if ((o->flags & SEC_RELOC) != 0)
427784865Sobrien	{
427884865Sobrien	  int target_index;
427984865Sobrien	  struct internal_reloc *internal_relocs;
428084865Sobrien	  struct internal_reloc *irel;
428184865Sobrien	  bfd_vma offset;
428284865Sobrien	  struct internal_reloc *irelend;
428384865Sobrien	  struct xcoff_link_hash_entry **rel_hash;
428484865Sobrien	  long r_symndx;
428584865Sobrien
428684865Sobrien	  /* Read in the relocs.  */
428784865Sobrien	  target_index = o->output_section->target_index;
428884865Sobrien	  internal_relocs = (xcoff_read_internal_relocs
4289130561Sobrien			     (input_bfd, o, FALSE, finfo->external_relocs,
4290130561Sobrien			      TRUE,
429184865Sobrien			      (finfo->section_info[target_index].relocs
429284865Sobrien			       + o->output_section->reloc_count)));
429384865Sobrien	  if (internal_relocs == NULL)
4294130561Sobrien	    return FALSE;
429584865Sobrien
429684865Sobrien	  /* Call processor specific code to relocate the section
429794536Sobrien	     contents.  */
429884865Sobrien	  if (! bfd_coff_relocate_section (output_bfd, finfo->info,
429984865Sobrien					   input_bfd, o,
430084865Sobrien					   contents,
430184865Sobrien					   internal_relocs,
430284865Sobrien					   finfo->internal_syms,
430384865Sobrien					   xcoff_data (input_bfd)->csects))
4304130561Sobrien	    return FALSE;
430584865Sobrien
430684865Sobrien	  offset = o->output_section->vma + o->output_offset - o->vma;
430784865Sobrien	  irel = internal_relocs;
430884865Sobrien	  irelend = irel + o->reloc_count;
430984865Sobrien	  rel_hash = (finfo->section_info[target_index].rel_hashes
431084865Sobrien		      + o->output_section->reloc_count);
431184865Sobrien	  for (; irel < irelend; irel++, rel_hash++)
431284865Sobrien	    {
431384865Sobrien	      struct xcoff_link_hash_entry *h = NULL;
431484865Sobrien	      struct internal_ldrel ldrel;
4315130561Sobrien	      bfd_boolean quiet;
431684865Sobrien
431784865Sobrien	      *rel_hash = NULL;
431884865Sobrien
431984865Sobrien	      /* Adjust the reloc address and symbol index.  */
432084865Sobrien
432184865Sobrien	      irel->r_vaddr += offset;
432284865Sobrien
432384865Sobrien	      r_symndx = irel->r_symndx;
432484865Sobrien
432584865Sobrien	      if (r_symndx == -1)
432684865Sobrien		h = NULL;
432784865Sobrien	      else
432884865Sobrien		h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
432984865Sobrien
433084865Sobrien	      if (r_symndx != -1 && finfo->info->strip != strip_all)
433184865Sobrien		{
433284865Sobrien		  if (h != NULL
433384865Sobrien		      && h->smclas != XMC_TD
433484865Sobrien		      && (irel->r_type == R_TOC
433584865Sobrien			  || irel->r_type == R_GL
433684865Sobrien			  || irel->r_type == R_TCL
433784865Sobrien			  || irel->r_type == R_TRL
433884865Sobrien			  || irel->r_type == R_TRLA))
433984865Sobrien		    {
434084865Sobrien		      /* This is a TOC relative reloc with a symbol
434194536Sobrien			 attached.  The symbol should be the one which
434294536Sobrien			 this reloc is for.  We want to make this
434394536Sobrien			 reloc against the TOC address of the symbol,
434494536Sobrien			 not the symbol itself.  */
434584865Sobrien		      BFD_ASSERT (h->toc_section != NULL);
434684865Sobrien		      BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
434784865Sobrien		      if (h->u.toc_indx != -1)
434884865Sobrien			irel->r_symndx = h->u.toc_indx;
434984865Sobrien		      else
435084865Sobrien			{
435184865Sobrien			  struct xcoff_toc_rel_hash *n;
435284865Sobrien			  struct xcoff_link_section_info *si;
435394536Sobrien			  bfd_size_type amt;
435484865Sobrien
4355218822Sdim			  amt = sizeof (* n);
4356218822Sdim			  n = bfd_alloc (finfo->output_bfd, amt);
435784865Sobrien			  if (n == NULL)
4358130561Sobrien			    return FALSE;
435984865Sobrien			  si = finfo->section_info + target_index;
436084865Sobrien			  n->next = si->toc_rel_hashes;
436184865Sobrien			  n->h = h;
436284865Sobrien			  n->rel = irel;
436384865Sobrien			  si->toc_rel_hashes = n;
436484865Sobrien			}
436584865Sobrien		    }
436684865Sobrien		  else if (h != NULL)
436784865Sobrien		    {
436884865Sobrien		      /* This is a global symbol.  */
436984865Sobrien		      if (h->indx >= 0)
437084865Sobrien			irel->r_symndx = h->indx;
437184865Sobrien		      else
437284865Sobrien			{
437384865Sobrien			  /* This symbol is being written at the end
437484865Sobrien			     of the file, and we do not yet know the
437584865Sobrien			     symbol index.  We save the pointer to the
437684865Sobrien			     hash table entry in the rel_hash list.
437784865Sobrien			     We set the indx field to -2 to indicate
437884865Sobrien			     that this symbol must not be stripped.  */
437984865Sobrien			  *rel_hash = h;
438084865Sobrien			  h->indx = -2;
438184865Sobrien			}
438284865Sobrien		    }
438384865Sobrien		  else
438484865Sobrien		    {
438584865Sobrien		      long indx;
438684865Sobrien
438784865Sobrien		      indx = finfo->sym_indices[r_symndx];
438884865Sobrien
438984865Sobrien		      if (indx == -1)
439084865Sobrien			{
439184865Sobrien			  struct internal_syment *is;
439284865Sobrien
439384865Sobrien			  /* Relocations against a TC0 TOC anchor are
439484865Sobrien			     automatically transformed to be against
439584865Sobrien			     the TOC anchor in the output file.  */
439684865Sobrien			  is = finfo->internal_syms + r_symndx;
439784865Sobrien			  if (is->n_sclass == C_HIDEXT
439884865Sobrien			      && is->n_numaux > 0)
439984865Sobrien			    {
4400218822Sdim			      void * auxptr;
440184865Sobrien			      union internal_auxent aux;
440284865Sobrien
4403218822Sdim			      auxptr = ((void *)
440484865Sobrien					(((bfd_byte *)
440584865Sobrien					  obj_coff_external_syms (input_bfd))
440684865Sobrien					 + ((r_symndx + is->n_numaux)
440784865Sobrien					    * isymesz)));
440884865Sobrien			      bfd_coff_swap_aux_in (input_bfd, auxptr,
440984865Sobrien						    is->n_type, is->n_sclass,
441084865Sobrien						    is->n_numaux - 1,
441184865Sobrien						    is->n_numaux,
4412218822Sdim						    (void *) &aux);
441384865Sobrien			      if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
441484865Sobrien				  && aux.x_csect.x_smclas == XMC_TC0)
441584865Sobrien				indx = finfo->toc_symindx;
441684865Sobrien			    }
441784865Sobrien			}
441884865Sobrien
441984865Sobrien		      if (indx != -1)
442084865Sobrien			irel->r_symndx = indx;
442184865Sobrien		      else
442284865Sobrien			{
442394536Sobrien
442484865Sobrien			  struct internal_syment *is;
442594536Sobrien
442684865Sobrien			  const char *name;
442784865Sobrien			  char buf[SYMNMLEN + 1];
442884865Sobrien
442984865Sobrien			  /* This reloc is against a symbol we are
443084865Sobrien			     stripping.  It would be possible to handle
443184865Sobrien			     this case, but I don't think it's worth it.  */
443284865Sobrien			  is = finfo->internal_syms + r_symndx;
443384865Sobrien
443484865Sobrien			  name = (_bfd_coff_internal_syment_name
443584865Sobrien				  (input_bfd, is, buf));
443694536Sobrien
443784865Sobrien			  if (name == NULL)
4438130561Sobrien			    return FALSE;
443984865Sobrien
444084865Sobrien			  if (! ((*finfo->info->callbacks->unattached_reloc)
444184865Sobrien				 (finfo->info, name, input_bfd, o,
444284865Sobrien				  irel->r_vaddr)))
4443130561Sobrien			    return FALSE;
444484865Sobrien			}
444584865Sobrien		    }
444684865Sobrien		}
444784865Sobrien
4448130561Sobrien	      quiet = FALSE;
444984865Sobrien	      switch (irel->r_type)
445084865Sobrien		{
445184865Sobrien		default:
445284865Sobrien		  if (h == NULL
445384865Sobrien		      || h->root.type == bfd_link_hash_defined
445484865Sobrien		      || h->root.type == bfd_link_hash_defweak
445584865Sobrien		      || h->root.type == bfd_link_hash_common)
445684865Sobrien		    break;
445784865Sobrien		  /* Fall through.  */
445884865Sobrien		case R_POS:
445984865Sobrien		case R_NEG:
446084865Sobrien		case R_RL:
446184865Sobrien		case R_RLA:
446284865Sobrien		  /* This reloc needs to be copied into the .loader
446384865Sobrien		     section.  */
446484865Sobrien		  ldrel.l_vaddr = irel->r_vaddr;
446584865Sobrien		  if (r_symndx == -1)
446694536Sobrien		    ldrel.l_symndx = -(bfd_size_type ) 1;
446784865Sobrien		  else if (h == NULL
446884865Sobrien			   || (h->root.type == bfd_link_hash_defined
446984865Sobrien			       || h->root.type == bfd_link_hash_defweak
447084865Sobrien			       || h->root.type == bfd_link_hash_common))
447184865Sobrien		    {
447284865Sobrien		      asection *sec;
447384865Sobrien
447484865Sobrien		      if (h == NULL)
447584865Sobrien			sec = xcoff_data (input_bfd)->csects[r_symndx];
447684865Sobrien		      else if (h->root.type == bfd_link_hash_common)
447784865Sobrien			sec = h->root.u.c.p->section;
447884865Sobrien		      else
447984865Sobrien			sec = h->root.u.def.section;
448084865Sobrien		      sec = sec->output_section;
448184865Sobrien
448284865Sobrien		      if (strcmp (sec->name, ".text") == 0)
448384865Sobrien			ldrel.l_symndx = 0;
448484865Sobrien		      else if (strcmp (sec->name, ".data") == 0)
448584865Sobrien			ldrel.l_symndx = 1;
448684865Sobrien		      else if (strcmp (sec->name, ".bss") == 0)
448784865Sobrien			ldrel.l_symndx = 2;
448884865Sobrien		      else
448984865Sobrien			{
449084865Sobrien			  (*_bfd_error_handler)
4491218822Sdim			    (_("%B: loader reloc in unrecognized section `%A'"),
4492218822Sdim			     input_bfd, sec);
449384865Sobrien			  bfd_set_error (bfd_error_nonrepresentable_section);
4494130561Sobrien			  return FALSE;
449584865Sobrien			}
449684865Sobrien		    }
449784865Sobrien		  else
449884865Sobrien		    {
4499130561Sobrien		      if (! finfo->info->relocatable
450084865Sobrien			  && (h->flags & XCOFF_DEF_DYNAMIC) == 0
450184865Sobrien			  && (h->flags & XCOFF_IMPORT) == 0)
450284865Sobrien			{
450384865Sobrien			  /* We already called the undefined_symbol
450484865Sobrien			     callback for this relocation, in
450584865Sobrien			     _bfd_ppc_xcoff_relocate_section.  Don't
450684865Sobrien			     issue any more warnings.  */
4507130561Sobrien			  quiet = TRUE;
450884865Sobrien			}
450984865Sobrien		      if (h->ldindx < 0 && ! quiet)
451084865Sobrien			{
451184865Sobrien			  (*_bfd_error_handler)
4512218822Sdim			    (_("%B: `%s' in loader reloc but not loader sym"),
4513218822Sdim			     input_bfd,
451484865Sobrien			     h->root.root.string);
451584865Sobrien			  bfd_set_error (bfd_error_bad_value);
4516130561Sobrien			  return FALSE;
451784865Sobrien			}
451884865Sobrien		      ldrel.l_symndx = h->ldindx;
451984865Sobrien		    }
452084865Sobrien		  ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
452184865Sobrien		  ldrel.l_rsecnm = o->output_section->target_index;
452284865Sobrien		  if (xcoff_hash_table (finfo->info)->textro
452384865Sobrien		      && strcmp (o->output_section->name, ".text") == 0
452484865Sobrien		      && ! quiet)
452584865Sobrien		    {
452684865Sobrien		      (*_bfd_error_handler)
4527218822Sdim			(_("%B: loader reloc in read-only section %A"),
4528218822Sdim			 input_bfd, o->output_section);
452984865Sobrien		      bfd_set_error (bfd_error_invalid_operation);
4530130561Sobrien		      return FALSE;
453184865Sobrien		    }
453294536Sobrien		  bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel,
453394536Sobrien					    finfo->ldrel);
453494536Sobrien
453594536Sobrien		  finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
453684865Sobrien		  break;
453784865Sobrien
453884865Sobrien		case R_TOC:
453984865Sobrien		case R_GL:
454084865Sobrien		case R_TCL:
454184865Sobrien		case R_TRL:
454284865Sobrien		case R_TRLA:
454384865Sobrien		  /* We should never need a .loader reloc for a TOC
454484865Sobrien		     relative reloc.  */
454584865Sobrien		  break;
454684865Sobrien		}
454784865Sobrien	    }
454884865Sobrien
454984865Sobrien	  o->output_section->reloc_count += o->reloc_count;
455084865Sobrien	}
455184865Sobrien
455284865Sobrien      /* Write out the modified section contents.  */
455384865Sobrien      if (! bfd_set_section_contents (output_bfd, o->output_section,
455494536Sobrien				      contents, (file_ptr) o->output_offset,
4555218822Sdim				      o->size))
4556130561Sobrien	return FALSE;
455784865Sobrien    }
455884865Sobrien
455984865Sobrien  obj_coff_keep_syms (input_bfd) = keep_syms;
456084865Sobrien
456184865Sobrien  if (! finfo->info->keep_memory)
456284865Sobrien    {
456384865Sobrien      if (! _bfd_coff_free_symbols (input_bfd))
4564130561Sobrien	return FALSE;
456584865Sobrien    }
456684865Sobrien
4567130561Sobrien  return TRUE;
456884865Sobrien}
456984865Sobrien
457084865Sobrien#undef N_TMASK
457184865Sobrien#undef N_BTSHFT
457284865Sobrien
4573218822Sdim/* Sort relocs by VMA.  This is called via qsort.  */
4574218822Sdim
4575218822Sdimstatic int
4576218822Sdimxcoff_sort_relocs (const void * p1, const void * p2)
4577218822Sdim{
4578218822Sdim  const struct internal_reloc *r1 = (const struct internal_reloc *) p1;
4579218822Sdim  const struct internal_reloc *r2 = (const struct internal_reloc *) p2;
4580218822Sdim
4581218822Sdim  if (r1->r_vaddr > r2->r_vaddr)
4582218822Sdim    return 1;
4583218822Sdim  else if (r1->r_vaddr < r2->r_vaddr)
4584218822Sdim    return -1;
4585218822Sdim  else
4586218822Sdim    return 0;
4587218822Sdim}
4588218822Sdim
458984865Sobrien/* Write out a non-XCOFF global symbol.  */
459084865Sobrien
4591130561Sobrienstatic bfd_boolean
4592218822Sdimxcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
459384865Sobrien{
459494536Sobrien  struct xcoff_final_link_info *finfo = (struct xcoff_final_link_info *) inf;
459584865Sobrien  bfd *output_bfd;
459684865Sobrien  bfd_byte *outsym;
459784865Sobrien  struct internal_syment isym;
459884865Sobrien  union internal_auxent aux;
4599130561Sobrien  bfd_boolean result;
460094536Sobrien  file_ptr pos;
460194536Sobrien  bfd_size_type amt;
460284865Sobrien
460384865Sobrien  output_bfd = finfo->output_bfd;
460484865Sobrien  outsym = finfo->outsyms;
460584865Sobrien
460694536Sobrien  if (h->root.type == bfd_link_hash_warning)
460794536Sobrien    {
460894536Sobrien      h = (struct xcoff_link_hash_entry *) h->root.u.i.link;
460994536Sobrien      if (h->root.type == bfd_link_hash_new)
4610130561Sobrien	return TRUE;
461194536Sobrien    }
461294536Sobrien
461384865Sobrien  /* If this symbol was garbage collected, just skip it.  */
461484865Sobrien  if (xcoff_hash_table (finfo->info)->gc
461584865Sobrien      && (h->flags & XCOFF_MARK) == 0)
4616130561Sobrien    return TRUE;
461784865Sobrien
461884865Sobrien  /* If we need a .loader section entry, write it out.  */
461984865Sobrien  if (h->ldsym != NULL)
462084865Sobrien    {
462184865Sobrien      struct internal_ldsym *ldsym;
462284865Sobrien      bfd *impbfd;
462384865Sobrien
462484865Sobrien      ldsym = h->ldsym;
462584865Sobrien
462684865Sobrien      if (h->root.type == bfd_link_hash_undefined
462784865Sobrien	  || h->root.type == bfd_link_hash_undefweak)
462884865Sobrien	{
462994536Sobrien
463084865Sobrien	  ldsym->l_value = 0;
463184865Sobrien	  ldsym->l_scnum = N_UNDEF;
463284865Sobrien	  ldsym->l_smtype = XTY_ER;
463384865Sobrien	  impbfd = h->root.u.undef.abfd;
463494536Sobrien
463584865Sobrien	}
463684865Sobrien      else if (h->root.type == bfd_link_hash_defined
463784865Sobrien	       || h->root.type == bfd_link_hash_defweak)
463884865Sobrien	{
463984865Sobrien	  asection *sec;
464084865Sobrien
464184865Sobrien	  sec = h->root.u.def.section;
464284865Sobrien	  ldsym->l_value = (sec->output_section->vma
464384865Sobrien			    + sec->output_offset
464484865Sobrien			    + h->root.u.def.value);
464584865Sobrien	  ldsym->l_scnum = sec->output_section->target_index;
464684865Sobrien	  ldsym->l_smtype = XTY_SD;
464784865Sobrien	  impbfd = sec->owner;
464894536Sobrien
464984865Sobrien	}
465084865Sobrien      else
465184865Sobrien	abort ();
465284865Sobrien
465384865Sobrien      if (((h->flags & XCOFF_DEF_REGULAR) == 0
465484865Sobrien	   && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
465584865Sobrien	  || (h->flags & XCOFF_IMPORT) != 0)
4656218822Sdim	/* Clear l_smtype
4657218822Sdim	   Import symbols are defined so the check above will make
4658218822Sdim	   the l_smtype XTY_SD.  But this is not correct, it should
4659218822Sdim	   be cleared.  */
4660218822Sdim	ldsym->l_smtype |= L_IMPORT;
466194536Sobrien
466284865Sobrien      if (((h->flags & XCOFF_DEF_REGULAR) != 0
466384865Sobrien	   && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
466484865Sobrien	  || (h->flags & XCOFF_EXPORT) != 0)
4665218822Sdim	ldsym->l_smtype |= L_EXPORT;
466694536Sobrien
466784865Sobrien      if ((h->flags & XCOFF_ENTRY) != 0)
4668218822Sdim	ldsym->l_smtype |= L_ENTRY;
466984865Sobrien
467094536Sobrien      if ((h->flags & XCOFF_RTINIT) != 0)
4671218822Sdim	ldsym->l_smtype = XTY_SD;
467294536Sobrien
467384865Sobrien      ldsym->l_smclas = h->smclas;
467484865Sobrien
467594536Sobrien      if (ldsym->l_smtype & L_IMPORT)
467694536Sobrien	{
467794536Sobrien	  if ((h->root.type == bfd_link_hash_defined
467894536Sobrien	       || h->root.type == bfd_link_hash_defweak)
467994536Sobrien	      && (h->root.u.def.value != 0))
4680218822Sdim	    ldsym->l_smclas = XMC_XO;
4681218822Sdim
468294536Sobrien	  else if ((h->flags & (XCOFF_SYSCALL32 | XCOFF_SYSCALL64)) ==
468394536Sobrien		   (XCOFF_SYSCALL32 | XCOFF_SYSCALL64))
4684218822Sdim	    ldsym->l_smclas = XMC_SV3264;
4685218822Sdim
468694536Sobrien	  else if (h->flags & XCOFF_SYSCALL32)
4687218822Sdim	    ldsym->l_smclas = XMC_SV;
4688218822Sdim
468994536Sobrien	  else if (h->flags & XCOFF_SYSCALL64)
4690218822Sdim	    ldsym->l_smclas = XMC_SV64;
469194536Sobrien	}
469294536Sobrien
469394536Sobrien      if (ldsym->l_ifile == -(bfd_size_type) 1)
469494536Sobrien	{
469594536Sobrien	  ldsym->l_ifile = 0;
469694536Sobrien	}
469784865Sobrien      else if (ldsym->l_ifile == 0)
469884865Sobrien	{
469984865Sobrien	  if ((ldsym->l_smtype & L_IMPORT) == 0)
4700218822Sdim	    ldsym->l_ifile = 0;
470184865Sobrien	  else if (impbfd == NULL)
4702218822Sdim	    ldsym->l_ifile = 0;
470384865Sobrien	  else
470484865Sobrien	    {
470584865Sobrien	      BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
470684865Sobrien	      ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
470784865Sobrien	    }
470884865Sobrien	}
470984865Sobrien
471084865Sobrien      ldsym->l_parm = 0;
471184865Sobrien
471284865Sobrien      BFD_ASSERT (h->ldindx >= 0);
471394536Sobrien
471494536Sobrien      bfd_xcoff_swap_ldsym_out (output_bfd, ldsym,
471594536Sobrien				(finfo->ldsym +
471694536Sobrien				 (h->ldindx - 3)
471794536Sobrien				 * bfd_xcoff_ldsymsz(finfo->output_bfd)));
471884865Sobrien      h->ldsym = NULL;
471984865Sobrien    }
472084865Sobrien
472184865Sobrien  /* If this symbol needs global linkage code, write it out.  */
472284865Sobrien  if (h->root.type == bfd_link_hash_defined
472384865Sobrien      && (h->root.u.def.section
472484865Sobrien	  == xcoff_hash_table (finfo->info)->linkage_section))
472584865Sobrien    {
472684865Sobrien      bfd_byte *p;
472784865Sobrien      bfd_vma tocoff;
472884865Sobrien      unsigned int i;
472984865Sobrien
473084865Sobrien      p = h->root.u.def.section->contents + h->root.u.def.value;
473184865Sobrien
473284865Sobrien      /* The first instruction in the global linkage code loads a
473394536Sobrien	 specific TOC element.  */
473484865Sobrien      tocoff = (h->descriptor->toc_section->output_section->vma
473584865Sobrien		+ h->descriptor->toc_section->output_offset
473684865Sobrien		- xcoff_data (output_bfd)->toc);
473794536Sobrien
473884865Sobrien      if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
4739218822Sdim	tocoff += h->descriptor->u.toc_offset;
474094536Sobrien
474194536Sobrien      /* The first instruction in the glink code needs to be
474294536Sobrien	 cooked to to hold the correct offset in the toc.  The
474394536Sobrien	 rest are just output raw.  */
474494536Sobrien      bfd_put_32 (output_bfd,
474594536Sobrien		  bfd_xcoff_glink_code(output_bfd, 0) | (tocoff & 0xffff), p);
474694536Sobrien
474794536Sobrien      /* Start with i == 1 to get past the first instruction done above
474894536Sobrien	 The /4 is because the glink code is in bytes and we are going
474994536Sobrien	 4 at a pop.  */
475094536Sobrien      for (i = 1; i < bfd_xcoff_glink_code_size(output_bfd) / 4; i++)
4751218822Sdim	bfd_put_32 (output_bfd,
4752218822Sdim		    (bfd_vma) bfd_xcoff_glink_code(output_bfd, i),
4753218822Sdim		    &p[4 * i]);
475484865Sobrien    }
475584865Sobrien
475684865Sobrien  /* If we created a TOC entry for this symbol, write out the required
475784865Sobrien     relocs.  */
475884865Sobrien  if ((h->flags & XCOFF_SET_TOC) != 0)
475984865Sobrien    {
476084865Sobrien      asection *tocsec;
476184865Sobrien      asection *osec;
476284865Sobrien      int oindx;
476384865Sobrien      struct internal_reloc *irel;
476484865Sobrien      struct internal_ldrel ldrel;
476584865Sobrien      struct internal_syment irsym;
476684865Sobrien      union internal_auxent iraux;
476784865Sobrien
476884865Sobrien      tocsec = h->toc_section;
476984865Sobrien      osec = tocsec->output_section;
477084865Sobrien      oindx = osec->target_index;
477184865Sobrien      irel = finfo->section_info[oindx].relocs + osec->reloc_count;
477284865Sobrien      irel->r_vaddr = (osec->vma
477384865Sobrien		       + tocsec->output_offset
477484865Sobrien		       + h->u.toc_offset);
477594536Sobrien
477684865Sobrien      if (h->indx >= 0)
4777218822Sdim	irel->r_symndx = h->indx;
477884865Sobrien      else
477984865Sobrien	{
478084865Sobrien	  h->indx = -2;
478184865Sobrien	  irel->r_symndx = obj_raw_syment_count (output_bfd);
478284865Sobrien	}
478394536Sobrien
478494536Sobrien      BFD_ASSERT (h->ldindx >= 0);
478594536Sobrien
478694536Sobrien      /* Initialize the aux union here instead of closer to when it is
478794536Sobrien	 written out below because the length of the csect depends on
478894536Sobrien	 whether the output is 32 or 64 bit.  */
478994536Sobrien      memset (&iraux, 0, sizeof iraux);
479094536Sobrien      iraux.x_csect.x_smtyp = XTY_SD;
4791218822Sdim      /* iraux.x_csect.x_scnlen.l = 4 or 8, see below.  */
479294536Sobrien      iraux.x_csect.x_smclas = XMC_TC;
479394536Sobrien
479494536Sobrien      /* 32 bit uses a 32 bit R_POS to do the relocations
479594536Sobrien	 64 bit uses a 64 bit R_POS to do the relocations
479694536Sobrien
479794536Sobrien	 Also needs to change the csect size : 4 for 32 bit, 8 for 64 bit
479894536Sobrien
479994536Sobrien	 Which one is determined by the backend.  */
480094536Sobrien      if (bfd_xcoff_is_xcoff64 (output_bfd))
480194536Sobrien	{
480294536Sobrien	  irel->r_size = 63;
480394536Sobrien	  iraux.x_csect.x_scnlen.l = 8;
480494536Sobrien	}
480594536Sobrien      else if (bfd_xcoff_is_xcoff32 (output_bfd))
480694536Sobrien	{
480794536Sobrien	  irel->r_size = 31;
480894536Sobrien	  iraux.x_csect.x_scnlen.l = 4;
480994536Sobrien	}
481094536Sobrien      else
4811218822Sdim	return FALSE;
4812218822Sdim
481384865Sobrien      irel->r_type = R_POS;
481484865Sobrien      finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
481584865Sobrien      ++osec->reloc_count;
481684865Sobrien
481784865Sobrien      ldrel.l_vaddr = irel->r_vaddr;
481884865Sobrien      ldrel.l_symndx = h->ldindx;
481994536Sobrien      ldrel.l_rtype = (irel->r_size << 8) | R_POS;
482084865Sobrien      ldrel.l_rsecnm = oindx;
482194536Sobrien      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
482294536Sobrien      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
482384865Sobrien
482494536Sobrien      /* We need to emit a symbol to define a csect which holds
482594536Sobrien	 the reloc.  */
482684865Sobrien      if (finfo->info->strip != strip_all)
482784865Sobrien	{
482894536Sobrien	  result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab,
482994536Sobrien					      &irsym, h->root.root.string);
4830130561Sobrien	  if (!result)
4831130561Sobrien	    return FALSE;
483284865Sobrien
483384865Sobrien	  irsym.n_value = irel->r_vaddr;
483484865Sobrien	  irsym.n_scnum = osec->target_index;
483584865Sobrien	  irsym.n_sclass = C_HIDEXT;
483684865Sobrien	  irsym.n_type = T_NULL;
483784865Sobrien	  irsym.n_numaux = 1;
483884865Sobrien
4839218822Sdim	  bfd_coff_swap_sym_out (output_bfd, (void *) &irsym, (void *) outsym);
484084865Sobrien	  outsym += bfd_coff_symesz (output_bfd);
484184865Sobrien
4842218822Sdim	  /* Note : iraux is initialized above.  */
4843218822Sdim	  bfd_coff_swap_aux_out (output_bfd, (void *) &iraux, T_NULL, C_HIDEXT,
4844218822Sdim				 0, 1, (void *) outsym);
484584865Sobrien	  outsym += bfd_coff_auxesz (output_bfd);
484684865Sobrien
484784865Sobrien	  if (h->indx >= 0)
484884865Sobrien	    {
484984865Sobrien	      /* We aren't going to write out the symbols below, so we
485084865Sobrien		 need to write them out now.  */
485194536Sobrien	      pos = obj_sym_filepos (output_bfd);
485294536Sobrien	      pos += (obj_raw_syment_count (output_bfd)
485394536Sobrien		      * bfd_coff_symesz (output_bfd));
485494536Sobrien	      amt = outsym - finfo->outsyms;
485594536Sobrien	      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
485694536Sobrien		  || bfd_bwrite (finfo->outsyms, amt, output_bfd) != amt)
4857130561Sobrien		return FALSE;
485884865Sobrien	      obj_raw_syment_count (output_bfd) +=
485984865Sobrien		(outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
486084865Sobrien
486184865Sobrien	      outsym = finfo->outsyms;
486284865Sobrien	    }
486384865Sobrien	}
486484865Sobrien    }
486584865Sobrien
486684865Sobrien  /* If this symbol is a specially defined function descriptor, write
486784865Sobrien     it out.  The first word is the address of the function code
486884865Sobrien     itself, the second word is the address of the TOC, and the third
486994536Sobrien     word is zero.
487094536Sobrien
487194536Sobrien     32 bit vs 64 bit
487294536Sobrien     The addresses for the 32 bit will take 4 bytes and the addresses
487394536Sobrien     for 64 bit will take 8 bytes.  Similar for the relocs.  This type
487494536Sobrien     of logic was also done above to create a TOC entry in
487594536Sobrien     xcoff_write_global_symbol.  */
487684865Sobrien  if ((h->flags & XCOFF_DESCRIPTOR) != 0
487784865Sobrien      && h->root.type == bfd_link_hash_defined
487884865Sobrien      && (h->root.u.def.section
487984865Sobrien	  == xcoff_hash_table (finfo->info)->descriptor_section))
488084865Sobrien    {
488184865Sobrien      asection *sec;
488284865Sobrien      asection *osec;
488384865Sobrien      int oindx;
488484865Sobrien      bfd_byte *p;
488584865Sobrien      struct xcoff_link_hash_entry *hentry;
488684865Sobrien      asection *esec;
488784865Sobrien      struct internal_reloc *irel;
488884865Sobrien      struct internal_ldrel ldrel;
488984865Sobrien      asection *tsec;
489094536Sobrien      unsigned int reloc_size, byte_size;
489184865Sobrien
489294536Sobrien      if (bfd_xcoff_is_xcoff64 (output_bfd))
489394536Sobrien	{
489494536Sobrien	  reloc_size = 63;
489594536Sobrien	  byte_size = 8;
489694536Sobrien	}
489794536Sobrien      else if (bfd_xcoff_is_xcoff32 (output_bfd))
489894536Sobrien	{
489994536Sobrien	  reloc_size = 31;
490094536Sobrien	  byte_size = 4;
490194536Sobrien	}
490294536Sobrien      else
4903218822Sdim	return FALSE;
490494536Sobrien
490584865Sobrien      sec = h->root.u.def.section;
490684865Sobrien      osec = sec->output_section;
490784865Sobrien      oindx = osec->target_index;
490884865Sobrien      p = sec->contents + h->root.u.def.value;
490984865Sobrien
491084865Sobrien      hentry = h->descriptor;
491184865Sobrien      BFD_ASSERT (hentry != NULL
491284865Sobrien		  && (hentry->root.type == bfd_link_hash_defined
491384865Sobrien		      || hentry->root.type == bfd_link_hash_defweak));
491484865Sobrien      esec = hentry->root.u.def.section;
491584865Sobrien
491684865Sobrien      irel = finfo->section_info[oindx].relocs + osec->reloc_count;
491784865Sobrien      irel->r_vaddr = (osec->vma
491884865Sobrien		       + sec->output_offset
491984865Sobrien		       + h->root.u.def.value);
492084865Sobrien      irel->r_symndx = esec->output_section->target_index;
492184865Sobrien      irel->r_type = R_POS;
492294536Sobrien      irel->r_size = reloc_size;
492384865Sobrien      finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
492484865Sobrien      ++osec->reloc_count;
492584865Sobrien
492684865Sobrien      ldrel.l_vaddr = irel->r_vaddr;
492784865Sobrien      if (strcmp (esec->output_section->name, ".text") == 0)
492884865Sobrien	ldrel.l_symndx = 0;
492984865Sobrien      else if (strcmp (esec->output_section->name, ".data") == 0)
493084865Sobrien	ldrel.l_symndx = 1;
493184865Sobrien      else if (strcmp (esec->output_section->name, ".bss") == 0)
493284865Sobrien	ldrel.l_symndx = 2;
493384865Sobrien      else
493484865Sobrien	{
493584865Sobrien	  (*_bfd_error_handler)
493684865Sobrien	    (_("%s: loader reloc in unrecognized section `%s'"),
493784865Sobrien	     bfd_get_filename (output_bfd),
493884865Sobrien	     esec->output_section->name);
493984865Sobrien	  bfd_set_error (bfd_error_nonrepresentable_section);
4940130561Sobrien	  return FALSE;
494184865Sobrien	}
494294536Sobrien      ldrel.l_rtype = (reloc_size << 8) | R_POS;
494384865Sobrien      ldrel.l_rsecnm = oindx;
494494536Sobrien      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
494594536Sobrien      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
494684865Sobrien
494794536Sobrien      /* There are three items to write out,
494894536Sobrien	 the address of the code
494994536Sobrien	 the address of the toc anchor
495094536Sobrien	 the environment pointer.
495194536Sobrien	 We are ignoring the environment pointer.  So set it to zero.  */
495294536Sobrien      if (bfd_xcoff_is_xcoff64 (output_bfd))
495394536Sobrien	{
495494536Sobrien	  bfd_put_64 (output_bfd,
495594536Sobrien		      (esec->output_section->vma + esec->output_offset
495694536Sobrien		       + hentry->root.u.def.value),
495794536Sobrien		      p);
495894536Sobrien	  bfd_put_64 (output_bfd, xcoff_data (output_bfd)->toc, p + 8);
495994536Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, p + 16);
496094536Sobrien	}
496194536Sobrien      else
496294536Sobrien	{
496394536Sobrien	  /* 32 bit backend
496494536Sobrien	     This logic was already called above so the error case where
496594536Sobrien	     the backend is neither has already been checked.  */
496694536Sobrien	  bfd_put_32 (output_bfd,
496794536Sobrien		      (esec->output_section->vma + esec->output_offset
496894536Sobrien		       + hentry->root.u.def.value),
496994536Sobrien		      p);
497094536Sobrien	  bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
497194536Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, p + 8);
497294536Sobrien	}
497384865Sobrien
497484865Sobrien      tsec = coff_section_from_bfd_index (output_bfd,
497584865Sobrien					  xcoff_data (output_bfd)->sntoc);
497684865Sobrien
497784865Sobrien      ++irel;
497884865Sobrien      irel->r_vaddr = (osec->vma
497984865Sobrien		       + sec->output_offset
498084865Sobrien		       + h->root.u.def.value
498194536Sobrien		       + byte_size);
498284865Sobrien      irel->r_symndx = tsec->output_section->target_index;
498384865Sobrien      irel->r_type = R_POS;
498494536Sobrien      irel->r_size = reloc_size;
498584865Sobrien      finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
498684865Sobrien      ++osec->reloc_count;
498784865Sobrien
498884865Sobrien      ldrel.l_vaddr = irel->r_vaddr;
498984865Sobrien      if (strcmp (tsec->output_section->name, ".text") == 0)
499084865Sobrien	ldrel.l_symndx = 0;
499184865Sobrien      else if (strcmp (tsec->output_section->name, ".data") == 0)
499284865Sobrien	ldrel.l_symndx = 1;
499384865Sobrien      else if (strcmp (tsec->output_section->name, ".bss") == 0)
499484865Sobrien	ldrel.l_symndx = 2;
499584865Sobrien      else
499684865Sobrien	{
499784865Sobrien	  (*_bfd_error_handler)
499884865Sobrien	    (_("%s: loader reloc in unrecognized section `%s'"),
499984865Sobrien	     bfd_get_filename (output_bfd),
500084865Sobrien	     tsec->output_section->name);
500184865Sobrien	  bfd_set_error (bfd_error_nonrepresentable_section);
5002130561Sobrien	  return FALSE;
500384865Sobrien	}
500494536Sobrien      ldrel.l_rtype = (reloc_size << 8) | R_POS;
500584865Sobrien      ldrel.l_rsecnm = oindx;
500694536Sobrien      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
500794536Sobrien      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
500884865Sobrien    }
500984865Sobrien
501084865Sobrien  if (h->indx >= 0 || finfo->info->strip == strip_all)
501184865Sobrien    {
501284865Sobrien      BFD_ASSERT (outsym == finfo->outsyms);
5013130561Sobrien      return TRUE;
501484865Sobrien    }
501584865Sobrien
501684865Sobrien  if (h->indx != -2
501784865Sobrien      && (finfo->info->strip == strip_all
501884865Sobrien	  || (finfo->info->strip == strip_some
501994536Sobrien	      && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
5020130561Sobrien				  FALSE, FALSE) == NULL)))
502184865Sobrien    {
502284865Sobrien      BFD_ASSERT (outsym == finfo->outsyms);
5023130561Sobrien      return TRUE;
502484865Sobrien    }
502584865Sobrien
502684865Sobrien  if (h->indx != -2
502784865Sobrien      && (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
502884865Sobrien    {
502984865Sobrien      BFD_ASSERT (outsym == finfo->outsyms);
5030130561Sobrien      return TRUE;
503184865Sobrien    }
503284865Sobrien
503384865Sobrien  memset (&aux, 0, sizeof aux);
503484865Sobrien
503584865Sobrien  h->indx = obj_raw_syment_count (output_bfd);
503684865Sobrien
503794536Sobrien  result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &isym,
503894536Sobrien				      h->root.root.string);
5039130561Sobrien  if (!result)
5040130561Sobrien    return FALSE;
504184865Sobrien
504284865Sobrien  if (h->root.type == bfd_link_hash_undefined
504384865Sobrien      || h->root.type == bfd_link_hash_undefweak)
504484865Sobrien    {
504584865Sobrien      isym.n_value = 0;
504684865Sobrien      isym.n_scnum = N_UNDEF;
504784865Sobrien      isym.n_sclass = C_EXT;
504884865Sobrien      aux.x_csect.x_smtyp = XTY_ER;
504984865Sobrien    }
505084865Sobrien  else if ((h->root.type == bfd_link_hash_defined
505184865Sobrien	    || h->root.type == bfd_link_hash_defweak)
505284865Sobrien	   && h->smclas == XMC_XO)
505384865Sobrien    {
505484865Sobrien      BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
505584865Sobrien      isym.n_value = h->root.u.def.value;
505684865Sobrien      isym.n_scnum = N_UNDEF;
505784865Sobrien      isym.n_sclass = C_EXT;
505884865Sobrien      aux.x_csect.x_smtyp = XTY_ER;
505984865Sobrien    }
506084865Sobrien  else if (h->root.type == bfd_link_hash_defined
506184865Sobrien	   || h->root.type == bfd_link_hash_defweak)
506284865Sobrien    {
506384865Sobrien      struct xcoff_link_size_list *l;
506484865Sobrien
506584865Sobrien      isym.n_value = (h->root.u.def.section->output_section->vma
506684865Sobrien		      + h->root.u.def.section->output_offset
506784865Sobrien		      + h->root.u.def.value);
5068104834Sobrien      if (bfd_is_abs_section (h->root.u.def.section->output_section))
5069104834Sobrien	isym.n_scnum = N_ABS;
5070104834Sobrien      else
5071104834Sobrien	isym.n_scnum = h->root.u.def.section->output_section->target_index;
507284865Sobrien      isym.n_sclass = C_HIDEXT;
507384865Sobrien      aux.x_csect.x_smtyp = XTY_SD;
507484865Sobrien
507584865Sobrien      if ((h->flags & XCOFF_HAS_SIZE) != 0)
507684865Sobrien	{
507784865Sobrien	  for (l = xcoff_hash_table (finfo->info)->size_list;
507884865Sobrien	       l != NULL;
507984865Sobrien	       l = l->next)
508084865Sobrien	    {
508184865Sobrien	      if (l->h == h)
508284865Sobrien		{
508384865Sobrien		  aux.x_csect.x_scnlen.l = l->size;
508484865Sobrien		  break;
508584865Sobrien		}
508684865Sobrien	    }
508784865Sobrien	}
508884865Sobrien    }
508984865Sobrien  else if (h->root.type == bfd_link_hash_common)
509084865Sobrien    {
509184865Sobrien      isym.n_value = (h->root.u.c.p->section->output_section->vma
509284865Sobrien		      + h->root.u.c.p->section->output_offset);
509384865Sobrien      isym.n_scnum = h->root.u.c.p->section->output_section->target_index;
509484865Sobrien      isym.n_sclass = C_EXT;
509584865Sobrien      aux.x_csect.x_smtyp = XTY_CM;
509684865Sobrien      aux.x_csect.x_scnlen.l = h->root.u.c.size;
509784865Sobrien    }
509884865Sobrien  else
509984865Sobrien    abort ();
510084865Sobrien
510184865Sobrien  isym.n_type = T_NULL;
510284865Sobrien  isym.n_numaux = 1;
510384865Sobrien
5104218822Sdim  bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
510584865Sobrien  outsym += bfd_coff_symesz (output_bfd);
510684865Sobrien
510784865Sobrien  aux.x_csect.x_smclas = h->smclas;
5108218822Sdim  bfd_coff_swap_aux_out (output_bfd, (void *) &aux, T_NULL, isym.n_sclass, 0, 1,
5109218822Sdim			 (void *) outsym);
511084865Sobrien  outsym += bfd_coff_auxesz (output_bfd);
511184865Sobrien
511284865Sobrien  if ((h->root.type == bfd_link_hash_defined
511384865Sobrien       || h->root.type == bfd_link_hash_defweak)
511484865Sobrien      && h->smclas != XMC_XO)
511584865Sobrien    {
511684865Sobrien      /* We just output an SD symbol.  Now output an LD symbol.  */
511784865Sobrien      h->indx += 2;
511884865Sobrien
511984865Sobrien      isym.n_sclass = C_EXT;
5120218822Sdim      bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
512184865Sobrien      outsym += bfd_coff_symesz (output_bfd);
512284865Sobrien
512384865Sobrien      aux.x_csect.x_smtyp = XTY_LD;
512484865Sobrien      aux.x_csect.x_scnlen.l = obj_raw_syment_count (output_bfd);
5125218822Sdim      bfd_coff_swap_aux_out (output_bfd, (void *) &aux, T_NULL, C_EXT, 0, 1,
5126218822Sdim			     (void *) outsym);
512784865Sobrien      outsym += bfd_coff_auxesz (output_bfd);
512884865Sobrien    }
512984865Sobrien
513094536Sobrien  pos = obj_sym_filepos (output_bfd);
513194536Sobrien  pos += obj_raw_syment_count (output_bfd) * bfd_coff_symesz (output_bfd);
513294536Sobrien  amt = outsym - finfo->outsyms;
513394536Sobrien  if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
513494536Sobrien      || bfd_bwrite (finfo->outsyms, amt, output_bfd) != amt)
5135130561Sobrien    return FALSE;
513684865Sobrien  obj_raw_syment_count (output_bfd) +=
513784865Sobrien    (outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
513884865Sobrien
5139130561Sobrien  return TRUE;
514084865Sobrien}
514184865Sobrien
514284865Sobrien/* Handle a link order which is supposed to generate a reloc.  */
514384865Sobrien
5144130561Sobrienstatic bfd_boolean
5145218822Sdimxcoff_reloc_link_order (bfd *output_bfd,
5146218822Sdim			struct xcoff_final_link_info *finfo,
5147218822Sdim			asection *output_section,
5148218822Sdim			struct bfd_link_order *link_order)
514984865Sobrien{
515084865Sobrien  reloc_howto_type *howto;
515184865Sobrien  struct xcoff_link_hash_entry *h;
515284865Sobrien  asection *hsec;
515384865Sobrien  bfd_vma hval;
515484865Sobrien  bfd_vma addend;
515584865Sobrien  struct internal_reloc *irel;
515684865Sobrien  struct xcoff_link_hash_entry **rel_hash_ptr;
515784865Sobrien  struct internal_ldrel ldrel;
515884865Sobrien
515984865Sobrien  if (link_order->type == bfd_section_reloc_link_order)
5160218822Sdim    /* We need to somehow locate a symbol in the right section.  The
5161218822Sdim       symbol must either have a value of zero, or we must adjust
5162218822Sdim       the addend by the value of the symbol.  FIXME: Write this
5163218822Sdim       when we need it.  The old linker couldn't handle this anyhow.  */
5164218822Sdim    abort ();
516584865Sobrien
516684865Sobrien  howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
516784865Sobrien  if (howto == NULL)
516884865Sobrien    {
516984865Sobrien      bfd_set_error (bfd_error_bad_value);
5170130561Sobrien      return FALSE;
517184865Sobrien    }
517284865Sobrien
517384865Sobrien  h = ((struct xcoff_link_hash_entry *)
517484865Sobrien       bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
517584865Sobrien				     link_order->u.reloc.p->u.name,
5176130561Sobrien				     FALSE, FALSE, TRUE));
517784865Sobrien  if (h == NULL)
517884865Sobrien    {
517984865Sobrien      if (! ((*finfo->info->callbacks->unattached_reloc)
5180218822Sdim	     (finfo->info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0)))
5181130561Sobrien	return FALSE;
5182130561Sobrien      return TRUE;
518384865Sobrien    }
518484865Sobrien
518584865Sobrien  if (h->root.type == bfd_link_hash_common)
518684865Sobrien    {
518784865Sobrien      hsec = h->root.u.c.p->section;
518884865Sobrien      hval = 0;
518984865Sobrien    }
519084865Sobrien  else if (h->root.type == bfd_link_hash_defined
519184865Sobrien	   || h->root.type == bfd_link_hash_defweak)
519284865Sobrien    {
519384865Sobrien      hsec = h->root.u.def.section;
519484865Sobrien      hval = h->root.u.def.value;
519584865Sobrien    }
519684865Sobrien  else
519784865Sobrien    {
519884865Sobrien      hsec = NULL;
519984865Sobrien      hval = 0;
520084865Sobrien    }
520184865Sobrien
520284865Sobrien  addend = link_order->u.reloc.p->addend;
520384865Sobrien  if (hsec != NULL)
520484865Sobrien    addend += (hsec->output_section->vma
520584865Sobrien	       + hsec->output_offset
520684865Sobrien	       + hval);
520784865Sobrien
520884865Sobrien  if (addend != 0)
520984865Sobrien    {
521084865Sobrien      bfd_size_type size;
521184865Sobrien      bfd_byte *buf;
521284865Sobrien      bfd_reloc_status_type rstat;
5213130561Sobrien      bfd_boolean ok;
521484865Sobrien
521584865Sobrien      size = bfd_get_reloc_size (howto);
5216218822Sdim      buf = bfd_zmalloc (size);
521784865Sobrien      if (buf == NULL)
5218130561Sobrien	return FALSE;
521984865Sobrien
522084865Sobrien      rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
522184865Sobrien      switch (rstat)
522284865Sobrien	{
522384865Sobrien	case bfd_reloc_ok:
522484865Sobrien	  break;
522584865Sobrien	default:
522684865Sobrien	case bfd_reloc_outofrange:
522784865Sobrien	  abort ();
522884865Sobrien	case bfd_reloc_overflow:
522984865Sobrien	  if (! ((*finfo->info->callbacks->reloc_overflow)
5230218822Sdim		 (finfo->info, NULL, link_order->u.reloc.p->u.name,
5231218822Sdim		  howto->name, addend, NULL, NULL, (bfd_vma) 0)))
523284865Sobrien	    {
523384865Sobrien	      free (buf);
5234130561Sobrien	      return FALSE;
523584865Sobrien	    }
523684865Sobrien	  break;
523784865Sobrien	}
5238218822Sdim      ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf,
523984865Sobrien				     (file_ptr) link_order->offset, size);
524084865Sobrien      free (buf);
524184865Sobrien      if (! ok)
5242130561Sobrien	return FALSE;
524384865Sobrien    }
524484865Sobrien
524584865Sobrien  /* Store the reloc information in the right place.  It will get
524684865Sobrien     swapped and written out at the end of the final_link routine.  */
524784865Sobrien  irel = (finfo->section_info[output_section->target_index].relocs
524884865Sobrien	  + output_section->reloc_count);
524984865Sobrien  rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
525084865Sobrien		  + output_section->reloc_count);
525184865Sobrien
525284865Sobrien  memset (irel, 0, sizeof (struct internal_reloc));
525384865Sobrien  *rel_hash_ptr = NULL;
525484865Sobrien
525584865Sobrien  irel->r_vaddr = output_section->vma + link_order->offset;
525684865Sobrien
525784865Sobrien  if (h->indx >= 0)
525884865Sobrien    irel->r_symndx = h->indx;
525984865Sobrien  else
526084865Sobrien    {
526184865Sobrien      /* Set the index to -2 to force this symbol to get written out.  */
526284865Sobrien      h->indx = -2;
526384865Sobrien      *rel_hash_ptr = h;
526484865Sobrien      irel->r_symndx = 0;
526584865Sobrien    }
526684865Sobrien
526784865Sobrien  irel->r_type = howto->type;
526884865Sobrien  irel->r_size = howto->bitsize - 1;
526984865Sobrien  if (howto->complain_on_overflow == complain_overflow_signed)
527084865Sobrien    irel->r_size |= 0x80;
527184865Sobrien
527284865Sobrien  ++output_section->reloc_count;
527384865Sobrien
527484865Sobrien  /* Now output the reloc to the .loader section.  */
527584865Sobrien
527684865Sobrien  ldrel.l_vaddr = irel->r_vaddr;
527784865Sobrien
527884865Sobrien  if (hsec != NULL)
527984865Sobrien    {
528084865Sobrien      const char *secname;
528184865Sobrien
528284865Sobrien      secname = hsec->output_section->name;
528384865Sobrien
528484865Sobrien      if (strcmp (secname, ".text") == 0)
528584865Sobrien	ldrel.l_symndx = 0;
528684865Sobrien      else if (strcmp (secname, ".data") == 0)
528784865Sobrien	ldrel.l_symndx = 1;
528884865Sobrien      else if (strcmp (secname, ".bss") == 0)
528984865Sobrien	ldrel.l_symndx = 2;
529084865Sobrien      else
529184865Sobrien	{
529284865Sobrien	  (*_bfd_error_handler)
529384865Sobrien	    (_("%s: loader reloc in unrecognized section `%s'"),
529484865Sobrien	     bfd_get_filename (output_bfd), secname);
529584865Sobrien	  bfd_set_error (bfd_error_nonrepresentable_section);
5296130561Sobrien	  return FALSE;
529784865Sobrien	}
529884865Sobrien    }
529984865Sobrien  else
530084865Sobrien    {
530184865Sobrien      if (h->ldindx < 0)
530284865Sobrien	{
530384865Sobrien	  (*_bfd_error_handler)
530484865Sobrien	    (_("%s: `%s' in loader reloc but not loader sym"),
530584865Sobrien	     bfd_get_filename (output_bfd),
530684865Sobrien	     h->root.root.string);
530784865Sobrien	  bfd_set_error (bfd_error_bad_value);
5308130561Sobrien	  return FALSE;
530984865Sobrien	}
531084865Sobrien      ldrel.l_symndx = h->ldindx;
531184865Sobrien    }
531284865Sobrien
531384865Sobrien  ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
531484865Sobrien  ldrel.l_rsecnm = output_section->target_index;
531594536Sobrien  bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
531694536Sobrien  finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
531784865Sobrien
5318130561Sobrien  return TRUE;
531984865Sobrien}
532084865Sobrien
5321218822Sdim/* Do the final link step.  */
532284865Sobrien
5323218822Sdimbfd_boolean
5324218822Sdim_bfd_xcoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
532584865Sobrien{
5326218822Sdim  bfd_size_type symesz;
5327218822Sdim  struct xcoff_final_link_info finfo;
5328218822Sdim  asection *o;
5329218822Sdim  struct bfd_link_order *p;
5330218822Sdim  bfd_size_type max_contents_size;
5331218822Sdim  bfd_size_type max_sym_count;
5332218822Sdim  bfd_size_type max_lineno_count;
5333218822Sdim  bfd_size_type max_reloc_count;
5334218822Sdim  bfd_size_type max_output_reloc_count;
5335218822Sdim  file_ptr rel_filepos;
5336218822Sdim  unsigned int relsz;
5337218822Sdim  file_ptr line_filepos;
5338218822Sdim  unsigned int linesz;
5339218822Sdim  bfd *sub;
5340218822Sdim  bfd_byte *external_relocs = NULL;
5341218822Sdim  char strbuf[STRING_SIZE_SIZE];
5342218822Sdim  file_ptr pos;
5343218822Sdim  bfd_size_type amt;
534484865Sobrien
5345218822Sdim  if (info->shared)
5346218822Sdim    abfd->flags |= DYNAMIC;
5347218822Sdim
5348218822Sdim  symesz = bfd_coff_symesz (abfd);
5349218822Sdim
5350218822Sdim  finfo.info = info;
5351218822Sdim  finfo.output_bfd = abfd;
5352218822Sdim  finfo.strtab = NULL;
5353218822Sdim  finfo.section_info = NULL;
5354218822Sdim  finfo.last_file_index = -1;
5355218822Sdim  finfo.toc_symindx = -1;
5356218822Sdim  finfo.internal_syms = NULL;
5357218822Sdim  finfo.sym_indices = NULL;
5358218822Sdim  finfo.outsyms = NULL;
5359218822Sdim  finfo.linenos = NULL;
5360218822Sdim  finfo.contents = NULL;
5361218822Sdim  finfo.external_relocs = NULL;
5362218822Sdim
5363218822Sdim  finfo.ldsym = (xcoff_hash_table (info)->loader_section->contents
5364218822Sdim		 + bfd_xcoff_ldhdrsz (abfd));
5365218822Sdim  finfo.ldrel = (xcoff_hash_table (info)->loader_section->contents
5366218822Sdim		 + bfd_xcoff_ldhdrsz(abfd)
5367218822Sdim		 + (xcoff_hash_table (info)->ldhdr.l_nsyms
5368218822Sdim		    * bfd_xcoff_ldsymsz(abfd)));
5369218822Sdim
5370218822Sdim  xcoff_data (abfd)->coff.link_info = info;
5371218822Sdim
5372218822Sdim  finfo.strtab = _bfd_stringtab_init ();
5373218822Sdim  if (finfo.strtab == NULL)
5374218822Sdim    goto error_return;
5375218822Sdim
5376218822Sdim  /* Count the line number and relocation entries required for the
5377218822Sdim     output file.  Determine a few maximum sizes.  */
5378218822Sdim  max_contents_size = 0;
5379218822Sdim  max_lineno_count = 0;
5380218822Sdim  max_reloc_count = 0;
5381218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
5382218822Sdim    {
5383218822Sdim      o->reloc_count = 0;
5384218822Sdim      o->lineno_count = 0;
5385218822Sdim      for (p = o->map_head.link_order; p != NULL; p = p->next)
5386218822Sdim	{
5387218822Sdim	  if (p->type == bfd_indirect_link_order)
5388218822Sdim	    {
5389218822Sdim	      asection *sec;
5390218822Sdim
5391218822Sdim	      sec = p->u.indirect.section;
5392218822Sdim
5393218822Sdim	      /* Mark all sections which are to be included in the
5394218822Sdim		 link.  This will normally be every section.  We need
5395218822Sdim		 to do this so that we can identify any sections which
5396218822Sdim		 the linker has decided to not include.  */
5397218822Sdim	      sec->linker_mark = TRUE;
5398218822Sdim
5399218822Sdim	      if (info->strip == strip_none
5400218822Sdim		  || info->strip == strip_some)
5401218822Sdim		o->lineno_count += sec->lineno_count;
5402218822Sdim
5403218822Sdim	      o->reloc_count += sec->reloc_count;
5404218822Sdim
5405218822Sdim	      if (sec->rawsize > max_contents_size)
5406218822Sdim		max_contents_size = sec->rawsize;
5407218822Sdim	      if (sec->size > max_contents_size)
5408218822Sdim		max_contents_size = sec->size;
5409218822Sdim	      if (sec->lineno_count > max_lineno_count)
5410218822Sdim		max_lineno_count = sec->lineno_count;
5411218822Sdim	      if (coff_section_data (sec->owner, sec) != NULL
5412218822Sdim		  && xcoff_section_data (sec->owner, sec) != NULL
5413218822Sdim		  && (xcoff_section_data (sec->owner, sec)->lineno_count
5414218822Sdim		      > max_lineno_count))
5415218822Sdim		max_lineno_count =
5416218822Sdim		  xcoff_section_data (sec->owner, sec)->lineno_count;
5417218822Sdim	      if (sec->reloc_count > max_reloc_count)
5418218822Sdim		max_reloc_count = sec->reloc_count;
5419218822Sdim	    }
5420218822Sdim	  else if (p->type == bfd_section_reloc_link_order
5421218822Sdim		   || p->type == bfd_symbol_reloc_link_order)
5422218822Sdim	    ++o->reloc_count;
5423218822Sdim	}
5424218822Sdim    }
5425218822Sdim
5426218822Sdim  /* Compute the file positions for all the sections.  */
5427218822Sdim  if (abfd->output_has_begun)
5428218822Sdim    {
5429218822Sdim      if (xcoff_hash_table (info)->file_align != 0)
5430218822Sdim	abort ();
5431218822Sdim    }
543284865Sobrien  else
5433218822Sdim    {
5434218822Sdim      bfd_vma file_align;
543584865Sobrien
5436218822Sdim      file_align = xcoff_hash_table (info)->file_align;
5437218822Sdim      if (file_align != 0)
5438218822Sdim	{
5439218822Sdim	  bfd_boolean saw_contents;
5440218822Sdim	  int indx;
5441218822Sdim	  file_ptr sofar;
544284865Sobrien
5443218822Sdim	  /* Insert .pad sections before every section which has
5444218822Sdim	     contents and is loaded, if it is preceded by some other
5445218822Sdim	     section which has contents and is loaded.  */
5446218822Sdim	  saw_contents = TRUE;
5447218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
5448218822Sdim	    {
5449218822Sdim	      if (strcmp (o->name, ".pad") == 0)
5450218822Sdim		saw_contents = FALSE;
5451218822Sdim	      else if ((o->flags & SEC_HAS_CONTENTS) != 0
5452218822Sdim		       && (o->flags & SEC_LOAD) != 0)
5453218822Sdim		{
5454218822Sdim		  if (! saw_contents)
5455218822Sdim		    saw_contents = TRUE;
5456218822Sdim		  else
5457218822Sdim		    {
5458218822Sdim		      asection *n;
545984865Sobrien
5460218822Sdim		      /* Create a pad section and place it before the section
5461218822Sdim			 that needs padding.  This requires unlinking and
5462218822Sdim			 relinking the bfd's section list.  */
546384865Sobrien
5464218822Sdim		      n = bfd_make_section_anyway_with_flags (abfd, ".pad",
5465218822Sdim							      SEC_HAS_CONTENTS);
5466218822Sdim		      n->alignment_power = 0;
5467218822Sdim
5468218822Sdim		      bfd_section_list_remove (abfd, n);
5469218822Sdim		      bfd_section_list_insert_before (abfd, o, n);
5470218822Sdim		      saw_contents = FALSE;
5471218822Sdim		    }
5472218822Sdim		}
5473218822Sdim	    }
5474218822Sdim
5475218822Sdim	  /* Reset the section indices after inserting the new
5476218822Sdim	     sections.  */
5477218822Sdim	  indx = 0;
5478218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
5479218822Sdim	    {
5480218822Sdim	      ++indx;
5481218822Sdim	      o->target_index = indx;
5482218822Sdim	    }
5483218822Sdim	  BFD_ASSERT ((unsigned int) indx == abfd->section_count);
5484218822Sdim
5485218822Sdim	  /* Work out appropriate sizes for the .pad sections to force
5486218822Sdim	     each section to land on a page boundary.  This bit of
5487218822Sdim	     code knows what compute_section_file_positions is going
5488218822Sdim	     to do.  */
5489218822Sdim	  sofar = bfd_coff_filhsz (abfd);
5490218822Sdim	  sofar += bfd_coff_aoutsz (abfd);
5491218822Sdim	  sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
5492218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
5493218822Sdim	    if ((bfd_xcoff_is_reloc_count_overflow
5494218822Sdim		 (abfd, (bfd_vma) o->reloc_count))
5495218822Sdim		|| (bfd_xcoff_is_lineno_count_overflow
5496218822Sdim		    (abfd, (bfd_vma) o->lineno_count)))
5497218822Sdim	      /* 64 does not overflow, need to check if 32 does */
5498218822Sdim	      sofar += bfd_coff_scnhsz (abfd);
5499218822Sdim
5500218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
5501218822Sdim	    {
5502218822Sdim	      if (strcmp (o->name, ".pad") == 0)
5503218822Sdim		{
5504218822Sdim		  bfd_vma pageoff;
5505218822Sdim
5506218822Sdim		  BFD_ASSERT (o->size == 0);
5507218822Sdim		  pageoff = sofar & (file_align - 1);
5508218822Sdim		  if (pageoff != 0)
5509218822Sdim		    {
5510218822Sdim		      o->size = file_align - pageoff;
5511218822Sdim		      sofar += file_align - pageoff;
5512218822Sdim		      o->flags |= SEC_HAS_CONTENTS;
5513218822Sdim		    }
5514218822Sdim		}
5515218822Sdim	      else
5516218822Sdim		{
5517218822Sdim		  if ((o->flags & SEC_HAS_CONTENTS) != 0)
5518218822Sdim		    sofar += BFD_ALIGN (o->size,
5519218822Sdim					1 << o->alignment_power);
5520218822Sdim		}
5521218822Sdim	    }
5522218822Sdim	}
5523218822Sdim
5524218822Sdim      if (! bfd_coff_compute_section_file_positions (abfd))
5525218822Sdim	goto error_return;
5526218822Sdim    }
5527218822Sdim
5528218822Sdim  /* Allocate space for the pointers we need to keep for the relocs.  */
5529218822Sdim  {
5530218822Sdim    unsigned int i;
5531218822Sdim
5532218822Sdim    /* We use section_count + 1, rather than section_count, because
5533218822Sdim       the target_index fields are 1 based.  */
5534218822Sdim    amt = abfd->section_count + 1;
5535218822Sdim    amt *= sizeof (struct xcoff_link_section_info);
5536218822Sdim    finfo.section_info = bfd_malloc (amt);
5537218822Sdim    if (finfo.section_info == NULL)
5538218822Sdim      goto error_return;
5539218822Sdim    for (i = 0; i <= abfd->section_count; i++)
5540218822Sdim      {
5541218822Sdim	finfo.section_info[i].relocs = NULL;
5542218822Sdim	finfo.section_info[i].rel_hashes = NULL;
5543218822Sdim	finfo.section_info[i].toc_rel_hashes = NULL;
5544218822Sdim      }
5545218822Sdim  }
5546218822Sdim
5547218822Sdim  /* Set the file positions for the relocs.  */
5548218822Sdim  rel_filepos = obj_relocbase (abfd);
5549218822Sdim  relsz = bfd_coff_relsz (abfd);
5550218822Sdim  max_output_reloc_count = 0;
5551218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
5552218822Sdim    {
5553218822Sdim      if (o->reloc_count == 0)
5554218822Sdim	o->rel_filepos = 0;
5555218822Sdim      else
5556218822Sdim	{
5557218822Sdim	  /* A stripped file has no relocs.  However, we still
5558218822Sdim	     allocate the buffers, so that later code doesn't have to
5559218822Sdim	     worry about whether we are stripping or not.  */
5560218822Sdim	  if (info->strip == strip_all)
5561218822Sdim	    o->rel_filepos = 0;
5562218822Sdim	  else
5563218822Sdim	    {
5564218822Sdim	      o->flags |= SEC_RELOC;
5565218822Sdim	      o->rel_filepos = rel_filepos;
5566218822Sdim	      rel_filepos += o->reloc_count * relsz;
5567218822Sdim	    }
5568218822Sdim
5569218822Sdim	  /* We don't know the indices of global symbols until we have
5570218822Sdim	     written out all the local symbols.  For each section in
5571218822Sdim	     the output file, we keep an array of pointers to hash
5572218822Sdim	     table entries.  Each entry in the array corresponds to a
5573218822Sdim	     reloc.  When we find a reloc against a global symbol, we
5574218822Sdim	     set the corresponding entry in this array so that we can
5575218822Sdim	     fix up the symbol index after we have written out all the
5576218822Sdim	     local symbols.
5577218822Sdim
5578218822Sdim	     Because of this problem, we also keep the relocs in
5579218822Sdim	     memory until the end of the link.  This wastes memory.
5580218822Sdim	     We could backpatch the file later, I suppose, although it
5581218822Sdim	     would be slow.  */
5582218822Sdim	  amt = o->reloc_count;
5583218822Sdim	  amt *= sizeof (struct internal_reloc);
5584218822Sdim	  finfo.section_info[o->target_index].relocs = bfd_malloc (amt);
5585218822Sdim
5586218822Sdim	  amt = o->reloc_count;
5587218822Sdim	  amt *= sizeof (struct xcoff_link_hash_entry *);
5588218822Sdim	  finfo.section_info[o->target_index].rel_hashes = bfd_malloc (amt);
5589218822Sdim
5590218822Sdim	  if (finfo.section_info[o->target_index].relocs == NULL
5591218822Sdim	      || finfo.section_info[o->target_index].rel_hashes == NULL)
5592218822Sdim	    goto error_return;
5593218822Sdim
5594218822Sdim	  if (o->reloc_count > max_output_reloc_count)
5595218822Sdim	    max_output_reloc_count = o->reloc_count;
5596218822Sdim	}
5597218822Sdim    }
5598218822Sdim
5599218822Sdim  /* We now know the size of the relocs, so we can determine the file
5600218822Sdim     positions of the line numbers.  */
5601218822Sdim  line_filepos = rel_filepos;
5602218822Sdim  finfo.line_filepos = line_filepos;
5603218822Sdim  linesz = bfd_coff_linesz (abfd);
5604218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
5605218822Sdim    {
5606218822Sdim      if (o->lineno_count == 0)
5607218822Sdim	o->line_filepos = 0;
5608218822Sdim      else
5609218822Sdim	{
5610218822Sdim	  o->line_filepos = line_filepos;
5611218822Sdim	  line_filepos += o->lineno_count * linesz;
5612218822Sdim	}
5613218822Sdim
5614218822Sdim      /* Reset the reloc and lineno counts, so that we can use them to
5615218822Sdim	 count the number of entries we have output so far.  */
5616218822Sdim      o->reloc_count = 0;
5617218822Sdim      o->lineno_count = 0;
5618218822Sdim    }
5619218822Sdim
5620218822Sdim  obj_sym_filepos (abfd) = line_filepos;
5621218822Sdim
5622218822Sdim  /* Figure out the largest number of symbols in an input BFD.  Take
5623218822Sdim     the opportunity to clear the output_has_begun fields of all the
5624218822Sdim     input BFD's.  We want at least 6 symbols, since that is the
5625218822Sdim     number which xcoff_write_global_symbol may need.  */
5626218822Sdim  max_sym_count = 6;
5627218822Sdim  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
5628218822Sdim    {
5629218822Sdim      bfd_size_type sz;
5630218822Sdim
5631218822Sdim      sub->output_has_begun = FALSE;
5632218822Sdim      sz = obj_raw_syment_count (sub);
5633218822Sdim      if (sz > max_sym_count)
5634218822Sdim	max_sym_count = sz;
5635218822Sdim    }
5636218822Sdim
5637218822Sdim  /* Allocate some buffers used while linking.  */
5638218822Sdim  amt = max_sym_count * sizeof (struct internal_syment);
5639218822Sdim  finfo.internal_syms = bfd_malloc (amt);
5640218822Sdim
5641218822Sdim  amt = max_sym_count * sizeof (long);
5642218822Sdim  finfo.sym_indices = bfd_malloc (amt);
5643218822Sdim
5644218822Sdim  amt = (max_sym_count + 1) * symesz;
5645218822Sdim  finfo.outsyms = bfd_malloc (amt);
5646218822Sdim
5647218822Sdim  amt = max_lineno_count * bfd_coff_linesz (abfd);
5648218822Sdim  finfo.linenos = bfd_malloc (amt);
5649218822Sdim
5650218822Sdim  amt = max_contents_size;
5651218822Sdim  finfo.contents = bfd_malloc (amt);
5652218822Sdim
5653218822Sdim  amt = max_reloc_count * relsz;
5654218822Sdim  finfo.external_relocs = bfd_malloc (amt);
5655218822Sdim
5656218822Sdim  if ((finfo.internal_syms == NULL && max_sym_count > 0)
5657218822Sdim      || (finfo.sym_indices == NULL && max_sym_count > 0)
5658218822Sdim      || finfo.outsyms == NULL
5659218822Sdim      || (finfo.linenos == NULL && max_lineno_count > 0)
5660218822Sdim      || (finfo.contents == NULL && max_contents_size > 0)
5661218822Sdim      || (finfo.external_relocs == NULL && max_reloc_count > 0))
5662218822Sdim    goto error_return;
5663218822Sdim
5664218822Sdim  obj_raw_syment_count (abfd) = 0;
5665218822Sdim  xcoff_data (abfd)->toc = (bfd_vma) -1;
5666218822Sdim
5667218822Sdim  /* We now know the position of everything in the file, except that
5668218822Sdim     we don't know the size of the symbol table and therefore we don't
5669218822Sdim     know where the string table starts.  We just build the string
5670218822Sdim     table in memory as we go along.  We process all the relocations
5671218822Sdim     for a single input file at once.  */
5672218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
5673218822Sdim    {
5674218822Sdim      for (p = o->map_head.link_order; p != NULL; p = p->next)
5675218822Sdim	{
5676218822Sdim	  if (p->type == bfd_indirect_link_order
5677218822Sdim	      && p->u.indirect.section->owner->xvec == abfd->xvec)
5678218822Sdim	    {
5679218822Sdim	      sub = p->u.indirect.section->owner;
5680218822Sdim	      if (! sub->output_has_begun)
5681218822Sdim		{
5682218822Sdim		  if (! xcoff_link_input_bfd (&finfo, sub))
5683218822Sdim		    goto error_return;
5684218822Sdim		  sub->output_has_begun = TRUE;
5685218822Sdim		}
5686218822Sdim	    }
5687218822Sdim	  else if (p->type == bfd_section_reloc_link_order
5688218822Sdim		   || p->type == bfd_symbol_reloc_link_order)
5689218822Sdim	    {
5690218822Sdim	      if (! xcoff_reloc_link_order (abfd, &finfo, o, p))
5691218822Sdim		goto error_return;
5692218822Sdim	    }
5693218822Sdim	  else
5694218822Sdim	    {
5695218822Sdim	      if (! _bfd_default_link_order (abfd, info, o, p))
5696218822Sdim		goto error_return;
5697218822Sdim	    }
5698218822Sdim	}
5699218822Sdim    }
5700218822Sdim
5701218822Sdim  /* Free up the buffers used by xcoff_link_input_bfd.  */
5702218822Sdim  if (finfo.internal_syms != NULL)
5703218822Sdim    {
5704218822Sdim      free (finfo.internal_syms);
5705218822Sdim      finfo.internal_syms = NULL;
5706218822Sdim    }
5707218822Sdim  if (finfo.sym_indices != NULL)
5708218822Sdim    {
5709218822Sdim      free (finfo.sym_indices);
5710218822Sdim      finfo.sym_indices = NULL;
5711218822Sdim    }
5712218822Sdim  if (finfo.linenos != NULL)
5713218822Sdim    {
5714218822Sdim      free (finfo.linenos);
5715218822Sdim      finfo.linenos = NULL;
5716218822Sdim    }
5717218822Sdim  if (finfo.contents != NULL)
5718218822Sdim    {
5719218822Sdim      free (finfo.contents);
5720218822Sdim      finfo.contents = NULL;
5721218822Sdim    }
5722218822Sdim  if (finfo.external_relocs != NULL)
5723218822Sdim    {
5724218822Sdim      free (finfo.external_relocs);
5725218822Sdim      finfo.external_relocs = NULL;
5726218822Sdim    }
5727218822Sdim
5728218822Sdim  /* The value of the last C_FILE symbol is supposed to be -1.  Write
5729218822Sdim     it out again.  */
5730218822Sdim  if (finfo.last_file_index != -1)
5731218822Sdim    {
5732218822Sdim      finfo.last_file.n_value = -(bfd_vma) 1;
5733218822Sdim      bfd_coff_swap_sym_out (abfd, (void *) &finfo.last_file,
5734218822Sdim			     (void *) finfo.outsyms);
5735218822Sdim      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
5736218822Sdim      if (bfd_seek (abfd, pos, SEEK_SET) != 0
5737218822Sdim	  || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
5738218822Sdim	goto error_return;
5739218822Sdim    }
5740218822Sdim
5741218822Sdim  /* Write out all the global symbols which do not come from XCOFF
5742218822Sdim     input files.  */
5743218822Sdim  xcoff_link_hash_traverse (xcoff_hash_table (info),
5744218822Sdim			    xcoff_write_global_symbol,
5745218822Sdim			    (void *) &finfo);
5746218822Sdim
5747218822Sdim  if (finfo.outsyms != NULL)
5748218822Sdim    {
5749218822Sdim      free (finfo.outsyms);
5750218822Sdim      finfo.outsyms = NULL;
5751218822Sdim    }
5752218822Sdim
5753218822Sdim  /* Now that we have written out all the global symbols, we know the
5754218822Sdim     symbol indices to use for relocs against them, and we can finally
5755218822Sdim     write out the relocs.  */
5756218822Sdim  amt = max_output_reloc_count * relsz;
5757218822Sdim  external_relocs = bfd_malloc (amt);
5758218822Sdim  if (external_relocs == NULL && max_output_reloc_count != 0)
5759218822Sdim    goto error_return;
5760218822Sdim
5761218822Sdim  for (o = abfd->sections; o != NULL; o = o->next)
5762218822Sdim    {
5763218822Sdim      struct internal_reloc *irel;
5764218822Sdim      struct internal_reloc *irelend;
5765218822Sdim      struct xcoff_link_hash_entry **rel_hash;
5766218822Sdim      struct xcoff_toc_rel_hash *toc_rel_hash;
5767218822Sdim      bfd_byte *erel;
5768218822Sdim      bfd_size_type rel_size;
5769218822Sdim
5770218822Sdim      /* A stripped file has no relocs.  */
5771218822Sdim      if (info->strip == strip_all)
5772218822Sdim	{
5773218822Sdim	  o->reloc_count = 0;
5774218822Sdim	  continue;
5775218822Sdim	}
5776218822Sdim
5777218822Sdim      if (o->reloc_count == 0)
5778218822Sdim	continue;
5779218822Sdim
5780218822Sdim      irel = finfo.section_info[o->target_index].relocs;
5781218822Sdim      irelend = irel + o->reloc_count;
5782218822Sdim      rel_hash = finfo.section_info[o->target_index].rel_hashes;
5783218822Sdim      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
5784218822Sdim	{
5785218822Sdim	  if (*rel_hash != NULL)
5786218822Sdim	    {
5787218822Sdim	      if ((*rel_hash)->indx < 0)
5788218822Sdim		{
5789218822Sdim		  if (! ((*info->callbacks->unattached_reloc)
5790218822Sdim			 (info, (*rel_hash)->root.root.string,
5791218822Sdim			  NULL, o, irel->r_vaddr)))
5792218822Sdim		    goto error_return;
5793218822Sdim		  (*rel_hash)->indx = 0;
5794218822Sdim		}
5795218822Sdim	      irel->r_symndx = (*rel_hash)->indx;
5796218822Sdim	    }
5797218822Sdim	}
5798218822Sdim
5799218822Sdim      for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
5800218822Sdim	   toc_rel_hash != NULL;
5801218822Sdim	   toc_rel_hash = toc_rel_hash->next)
5802218822Sdim	{
5803218822Sdim	  if (toc_rel_hash->h->u.toc_indx < 0)
5804218822Sdim	    {
5805218822Sdim	      if (! ((*info->callbacks->unattached_reloc)
5806218822Sdim		     (info, toc_rel_hash->h->root.root.string,
5807218822Sdim		      NULL, o, toc_rel_hash->rel->r_vaddr)))
5808218822Sdim		goto error_return;
5809218822Sdim	      toc_rel_hash->h->u.toc_indx = 0;
5810218822Sdim	    }
5811218822Sdim	  toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
5812218822Sdim	}
5813218822Sdim
5814218822Sdim      /* XCOFF requires that the relocs be sorted by address.  We tend
5815218822Sdim	 to produce them in the order in which their containing csects
5816218822Sdim	 appear in the symbol table, which is not necessarily by
5817218822Sdim	 address.  So we sort them here.  There may be a better way to
5818218822Sdim	 do this.  */
5819218822Sdim      qsort ((void *) finfo.section_info[o->target_index].relocs,
5820218822Sdim	     o->reloc_count, sizeof (struct internal_reloc),
5821218822Sdim	     xcoff_sort_relocs);
5822218822Sdim
5823218822Sdim      irel = finfo.section_info[o->target_index].relocs;
5824218822Sdim      irelend = irel + o->reloc_count;
5825218822Sdim      erel = external_relocs;
5826218822Sdim      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
5827218822Sdim	bfd_coff_swap_reloc_out (abfd, (void *) irel, (void *) erel);
5828218822Sdim
5829218822Sdim      rel_size = relsz * o->reloc_count;
5830218822Sdim      if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
5831218822Sdim	  || bfd_bwrite ((void *) external_relocs, rel_size, abfd) != rel_size)
5832218822Sdim	goto error_return;
5833218822Sdim    }
5834218822Sdim
5835218822Sdim  if (external_relocs != NULL)
5836218822Sdim    {
5837218822Sdim      free (external_relocs);
5838218822Sdim      external_relocs = NULL;
5839218822Sdim    }
5840218822Sdim
5841218822Sdim  /* Free up the section information.  */
5842218822Sdim  if (finfo.section_info != NULL)
5843218822Sdim    {
5844218822Sdim      unsigned int i;
5845218822Sdim
5846218822Sdim      for (i = 0; i < abfd->section_count; i++)
5847218822Sdim	{
5848218822Sdim	  if (finfo.section_info[i].relocs != NULL)
5849218822Sdim	    free (finfo.section_info[i].relocs);
5850218822Sdim	  if (finfo.section_info[i].rel_hashes != NULL)
5851218822Sdim	    free (finfo.section_info[i].rel_hashes);
5852218822Sdim	}
5853218822Sdim      free (finfo.section_info);
5854218822Sdim      finfo.section_info = NULL;
5855218822Sdim    }
5856218822Sdim
5857218822Sdim  /* Write out the loader section contents.  */
5858218822Sdim  BFD_ASSERT ((bfd_byte *) finfo.ldrel
5859218822Sdim	      == (xcoff_hash_table (info)->loader_section->contents
5860218822Sdim		  + xcoff_hash_table (info)->ldhdr.l_impoff));
5861218822Sdim  o = xcoff_hash_table (info)->loader_section;
5862218822Sdim  if (! bfd_set_section_contents (abfd, o->output_section, o->contents,
5863218822Sdim				  (file_ptr) o->output_offset, o->size))
5864218822Sdim    goto error_return;
5865218822Sdim
5866218822Sdim  /* Write out the magic sections.  */
5867218822Sdim  o = xcoff_hash_table (info)->linkage_section;
5868218822Sdim  if (o->size > 0
5869218822Sdim      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
5870218822Sdim				     (file_ptr) o->output_offset,
5871218822Sdim				     o->size))
5872218822Sdim    goto error_return;
5873218822Sdim  o = xcoff_hash_table (info)->toc_section;
5874218822Sdim  if (o->size > 0
5875218822Sdim      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
5876218822Sdim				     (file_ptr) o->output_offset,
5877218822Sdim				     o->size))
5878218822Sdim    goto error_return;
5879218822Sdim  o = xcoff_hash_table (info)->descriptor_section;
5880218822Sdim  if (o->size > 0
5881218822Sdim      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
5882218822Sdim				     (file_ptr) o->output_offset,
5883218822Sdim				     o->size))
5884218822Sdim    goto error_return;
5885218822Sdim
5886218822Sdim  /* Write out the string table.  */
5887218822Sdim  pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
5888218822Sdim  if (bfd_seek (abfd, pos, SEEK_SET) != 0)
5889218822Sdim    goto error_return;
5890218822Sdim  H_PUT_32 (abfd,
5891218822Sdim	    _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
5892218822Sdim	    strbuf);
5893218822Sdim  amt = STRING_SIZE_SIZE;
5894218822Sdim  if (bfd_bwrite (strbuf, amt, abfd) != amt)
5895218822Sdim    goto error_return;
5896218822Sdim  if (! _bfd_stringtab_emit (abfd, finfo.strtab))
5897218822Sdim    goto error_return;
5898218822Sdim
5899218822Sdim  _bfd_stringtab_free (finfo.strtab);
5900218822Sdim
5901218822Sdim  /* Write out the debugging string table.  */
5902218822Sdim  o = xcoff_hash_table (info)->debug_section;
5903218822Sdim  if (o != NULL)
5904218822Sdim    {
5905218822Sdim      struct bfd_strtab_hash *debug_strtab;
5906218822Sdim
5907218822Sdim      debug_strtab = xcoff_hash_table (info)->debug_strtab;
5908218822Sdim      BFD_ASSERT (o->output_section->size - o->output_offset
5909218822Sdim		  >= _bfd_stringtab_size (debug_strtab));
5910218822Sdim      pos = o->output_section->filepos + o->output_offset;
5911218822Sdim      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
5912218822Sdim	goto error_return;
5913218822Sdim      if (! _bfd_stringtab_emit (abfd, debug_strtab))
5914218822Sdim	goto error_return;
5915218822Sdim    }
5916218822Sdim
5917218822Sdim  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
5918218822Sdim     not try to write out the symbols.  */
5919218822Sdim  bfd_get_symcount (abfd) = 0;
5920218822Sdim
5921218822Sdim  return TRUE;
5922218822Sdim
5923218822Sdim error_return:
5924218822Sdim  if (finfo.strtab != NULL)
5925218822Sdim    _bfd_stringtab_free (finfo.strtab);
5926218822Sdim
5927218822Sdim  if (finfo.section_info != NULL)
5928218822Sdim    {
5929218822Sdim      unsigned int i;
5930218822Sdim
5931218822Sdim      for (i = 0; i < abfd->section_count; i++)
5932218822Sdim	{
5933218822Sdim	  if (finfo.section_info[i].relocs != NULL)
5934218822Sdim	    free (finfo.section_info[i].relocs);
5935218822Sdim	  if (finfo.section_info[i].rel_hashes != NULL)
5936218822Sdim	    free (finfo.section_info[i].rel_hashes);
5937218822Sdim	}
5938218822Sdim      free (finfo.section_info);
5939218822Sdim    }
5940218822Sdim
5941218822Sdim  if (finfo.internal_syms != NULL)
5942218822Sdim    free (finfo.internal_syms);
5943218822Sdim  if (finfo.sym_indices != NULL)
5944218822Sdim    free (finfo.sym_indices);
5945218822Sdim  if (finfo.outsyms != NULL)
5946218822Sdim    free (finfo.outsyms);
5947218822Sdim  if (finfo.linenos != NULL)
5948218822Sdim    free (finfo.linenos);
5949218822Sdim  if (finfo.contents != NULL)
5950218822Sdim    free (finfo.contents);
5951218822Sdim  if (finfo.external_relocs != NULL)
5952218822Sdim    free (finfo.external_relocs);
5953218822Sdim  if (external_relocs != NULL)
5954218822Sdim    free (external_relocs);
5955218822Sdim  return FALSE;
5956218822Sdim}
5957