malloc (max_sym_count * sizeof (struct internal_syment))); finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long));
bfd_malloc (max_sym_count * sizeof (struct internal_syment))); finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
_bfd_xcoff_bfd_final_link (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  bfd_size_type symesz;  struct xcoff_final_link_info finfo;  asection *o;  struct bfd_link_order *p;  size_t max_contents_size;  size_t max_sym_count;  size_t max_lineno_count;  size_t max_reloc_count;  size_t max_output_reloc_count;  file_ptr rel_filepos;  unsigned int relsz;  file_ptr line_filepos;  unsigned int linesz;  bfd *sub;  bfd_byte *external_relocs = NULL;  char strbuf[STRING_SIZE_SIZE];  if (info->shared)    abfd->flags |= DYNAMIC;  symesz = bfd_coff_symesz (abfd);  finfo.info = info;  finfo.output_bfd = abfd;  finfo.strtab = NULL;  finfo.section_info = NULL;  finfo.last_file_index = -1;  finfo.toc_symindx = -1;  finfo.internal_syms = NULL;  finfo.sym_indices = NULL;  finfo.outsyms = NULL;  finfo.linenos = NULL;  finfo.contents = NULL;  finfo.external_relocs = NULL;  finfo.ldsym = ((struct external_ldsym *)		 (xcoff_hash_table (info)->loader_section->contents		  + LDHDRSZ));  finfo.ldrel = ((struct external_ldrel *)		 (xcoff_hash_table (info)->loader_section->contents		  + LDHDRSZ		  + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));  xcoff_data (abfd)->coff.link_info = info;  finfo.strtab = _bfd_stringtab_init ();  if (finfo.strtab == NULL)    goto error_return;  /* Count the line number and relocation entries required for the     output file.  Determine a few maximum sizes.  */  max_contents_size = 0;  max_lineno_count = 0;  max_reloc_count = 0;  for (o = abfd->sections; o != NULL; o = o->next)    {      o->reloc_count = 0;      o->lineno_count = 0;      for (p = o->link_order_head; p != NULL; p = p->next)	{	  if (p->type == bfd_indirect_link_order)	    {	      asection *sec;	      sec = p->u.indirect.section;	      if (info->strip == strip_none		  || info->strip == strip_some)		o->lineno_count += sec->lineno_count;	      o->reloc_count += sec->reloc_count;	      if (sec->_raw_size > max_contents_size)		max_contents_size = sec->_raw_size;	      if (sec->lineno_count > max_lineno_count)		max_lineno_count = sec->lineno_count;	      if (coff_section_data (sec->owner, sec) != NULL		  && xcoff_section_data (sec->owner, sec) != NULL		  && (xcoff_section_data (sec->owner, sec)->lineno_count		      > max_lineno_count))		max_lineno_count =		  xcoff_section_data (sec->owner, sec)->lineno_count;	      if (sec->reloc_count > max_reloc_count)		max_reloc_count = sec->reloc_count;	    }	  else if (p->type == bfd_section_reloc_link_order		   || p->type == bfd_symbol_reloc_link_order)	    ++o->reloc_count;	}    }  /* Compute the file positions for all the sections.  */  if (abfd->output_has_begun)    {      if (xcoff_hash_table (info)->file_align != 0)	abort ();    }  else    {      bfd_vma file_align;      file_align = xcoff_hash_table (info)->file_align;      if (file_align != 0)	{	  boolean saw_contents;	  int indx;	  asection **op;	  file_ptr sofar;	  /* Insert .pad sections before every section which has             contents and is loaded, if it is preceded by some other             section which has contents and is loaded.  */	  saw_contents = true;	  for (op = &abfd->sections; *op != NULL; op = &(*op)->next)	    {	      (*op)->target_index = indx;	      if (strcmp ((*op)->name, ".pad") == 0)		saw_contents = false;	      else if (((*op)->flags & SEC_HAS_CONTENTS) != 0		       && ((*op)->flags & SEC_LOAD) != 0)		{		  if (! saw_contents)		    saw_contents = true;		  else		    {		      asection *n, *hold;		      hold = *op;		      *op = NULL;		      n = bfd_make_section_anyway (abfd, ".pad");		      BFD_ASSERT (*op == n);		      n->next = hold;		      n->flags = SEC_HAS_CONTENTS;		      n->alignment_power = 0;		      saw_contents = false;		    }		}	    }	  /* Reset the section indices after inserting the new             sections.  */	  indx = 0;	  for (o = abfd->sections; o != NULL; o = o->next)	    {	      ++indx;	      o->target_index = indx;	    }	  BFD_ASSERT ((unsigned int) indx == abfd->section_count);	  /* Work out appropriate sizes for the .pad sections to force             each section to land on a page boundary.  This bit of             code knows what compute_section_file_positions is going             to do.  */	  sofar = bfd_coff_filhsz (abfd);	  sofar += bfd_coff_aoutsz (abfd);	  sofar += abfd->section_count * bfd_coff_scnhsz (abfd);	  for (o = abfd->sections; o != NULL; o = o->next)	    if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)	      sofar += bfd_coff_scnhsz (abfd);	  for (o = abfd->sections; o != NULL; o = o->next)	    {	      if (strcmp (o->name, ".pad") == 0)		{		  bfd_vma pageoff;		  BFD_ASSERT (o->_raw_size == 0);		  pageoff = sofar & (file_align - 1);		  if (pageoff != 0)		    {		      o->_raw_size = file_align - pageoff;		      sofar += file_align - pageoff;		      o->flags |= SEC_HAS_CONTENTS;		    }		}	      else		{		  if ((o->flags & SEC_HAS_CONTENTS) != 0)		    sofar += BFD_ALIGN (o->_raw_size,					1 << o->alignment_power);		}	    }	}      bfd_coff_compute_section_file_positions (abfd);    }  /* Allocate space for the pointers we need to keep for the relocs.  */  {    unsigned int i;    /* We use section_count + 1, rather than section_count, because       the target_index fields are 1 based.  */    finfo.section_info = ((struct xcoff_link_section_info *)			  malloc ((abfd->section_count + 1)				  * sizeof (struct xcoff_link_section_info)));    if (finfo.section_info == NULL)      {	bfd_set_error (bfd_error_no_memory);	goto error_return;      }    for (i = 0; i <= abfd->section_count; i++)      {	finfo.section_info[i].relocs = NULL;	finfo.section_info[i].rel_hashes = NULL;	finfo.section_info[i].toc_rel_hashes = NULL;      }  }  /* Set the file positions for the relocs.  */  rel_filepos = obj_relocbase (abfd);  relsz = bfd_coff_relsz (abfd);  max_output_reloc_count = 0;  for (o = abfd->sections; o != NULL; o = o->next)    {      if (o->reloc_count == 0)	o->rel_filepos = 0;      else	{	  o->flags |= SEC_RELOC;	  o->rel_filepos = rel_filepos;	  rel_filepos += o->reloc_count * relsz;	  /* We don't know the indices of global symbols until we have             written out all the local symbols.  For each section in             the output file, we keep an array of pointers to hash             table entries.  Each entry in the array corresponds to a             reloc.  When we find a reloc against a global symbol, we             set the corresponding entry in this array so that we can             fix up the symbol index after we have written out all the             local symbols.	     Because of this problem, we also keep the relocs in	     memory until the end of the link.  This wastes memory.	     We could backpatch the file later, I suppose, although it	     would be slow.  */	  finfo.section_info[o->target_index].relocs =	    ((struct internal_reloc *)	     malloc (o->reloc_count * sizeof (struct internal_reloc)));	  finfo.section_info[o->target_index].rel_hashes =	    ((struct xcoff_link_hash_entry **)	     malloc (o->reloc_count		     * sizeof (struct xcoff_link_hash_entry *)));	  if (finfo.section_info[o->target_index].relocs == NULL	      || finfo.section_info[o->target_index].rel_hashes == NULL)	    {	      bfd_set_error (bfd_error_no_memory);	      goto error_return;	    }	  if (o->reloc_count > max_output_reloc_count)	    max_output_reloc_count = o->reloc_count;	}    }  /* We now know the size of the relocs, so we can determine the file     positions of the line numbers.  */  line_filepos = rel_filepos;  finfo.line_filepos = line_filepos;  linesz = bfd_coff_linesz (abfd);  for (o = abfd->sections; o != NULL; o = o->next)    {      if (o->lineno_count == 0)	o->line_filepos = 0;      else	{	  o->line_filepos = line_filepos;	  line_filepos += o->lineno_count * linesz;	}      /* Reset the reloc and lineno counts, so that we can use them to	 count the number of entries we have output so far.  */      o->reloc_count = 0;      o->lineno_count = 0;    }  obj_sym_filepos (abfd) = line_filepos;  /* Figure out the largest number of symbols in an input BFD.  Take     the opportunity to clear the output_has_begun fields of all the     input BFD's.  We want at least 4 symbols, since that is the     number which xcoff_write_global_symbol may need.  */  max_sym_count = 4;  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)    {      size_t sz;      sub->output_has_begun = false;      sz = obj_raw_syment_count (sub);      if (sz > max_sym_count)	max_sym_count = sz;    }  /* Allocate some buffers used while linking.  */  finfo.internal_syms = ((struct internal_syment *)			 malloc (max_sym_count				 * sizeof (struct internal_syment)));  finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long));  finfo.outsyms = ((bfd_byte *)		   malloc ((size_t) ((max_sym_count + 1) * symesz)));  finfo.linenos = (bfd_byte *) malloc (max_lineno_count				       * bfd_coff_linesz (abfd));  finfo.contents = (bfd_byte *) malloc (max_contents_size);  finfo.external_relocs = (bfd_byte *) malloc (max_reloc_count * relsz);  if ((finfo.internal_syms == NULL && max_sym_count > 0)      || (finfo.sym_indices == NULL && max_sym_count > 0)      || finfo.outsyms == NULL      || (finfo.linenos == NULL && max_lineno_count > 0)      || (finfo.contents == NULL && max_contents_size > 0)      || (finfo.external_relocs == NULL && max_reloc_count > 0))    {      bfd_set_error (bfd_error_no_memory);      goto error_return;    }  obj_raw_syment_count (abfd) = 0;  xcoff_data (abfd)->toc = (bfd_vma) -1;  /* We now know the position of everything in the file, except that     we don't know the size of the symbol table and therefore we don't     know where the string table starts.  We just build the string     table in memory as we go along.  We process all the relocations     for a single input file at once.  */  for (o = abfd->sections; o != NULL; o = o->next)    {      for (p = o->link_order_head; p != NULL; p = p->next)	{	  if (p->type == bfd_indirect_link_order	      && p->u.indirect.section->owner->xvec == abfd->xvec)	    {	      sub = p->u.indirect.section->owner;	      if (! sub->output_has_begun)		{		  if (! xcoff_link_input_bfd (&finfo, sub))		    goto error_return;		  sub->output_has_begun = true;		}	    }	  else if (p->type == bfd_section_reloc_link_order		   || p->type == bfd_symbol_reloc_link_order)	    {	      if (! xcoff_reloc_link_order (abfd, &finfo, o, p))		goto error_return;	    }	  else	    {	      if (! _bfd_default_link_order (abfd, info, o, p))		goto error_return;	    }	}    }  /* Free up the buffers used by xcoff_link_input_bfd.  */  if (finfo.internal_syms != NULL)    {      free (finfo.internal_syms);      finfo.internal_syms = NULL;    }  if (finfo.sym_indices != NULL)    {      free (finfo.sym_indices);      finfo.sym_indices = NULL;    }  if (finfo.linenos != NULL)    {      free (finfo.linenos);      finfo.linenos = NULL;    }  if (finfo.contents != NULL)    {      free (finfo.contents);      finfo.contents = NULL;    }  if (finfo.external_relocs != NULL)    {      free (finfo.external_relocs);      finfo.external_relocs = NULL;    }  /* The value of the last C_FILE symbol is supposed to be -1.  Write     it out again.  */  if (finfo.last_file_index != -1)    {      finfo.last_file.n_value = -1;      bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,			     (PTR) finfo.outsyms);      if (bfd_seek (abfd,		    (obj_sym_filepos (abfd)		     + finfo.last_file_index * symesz),		    SEEK_SET) != 0	  || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)	goto error_return;    }  /* Write out all the global symbols which do not come from XCOFF     input files.  */  xcoff_link_hash_traverse (xcoff_hash_table (info),			    xcoff_write_global_symbol,			    (PTR) &finfo);  if (finfo.outsyms != NULL)    {      free (finfo.outsyms);      finfo.outsyms = NULL;    }  /* Now that we have written out all the global symbols, we know the     symbol indices to use for relocs against them, and we can finally     write out the relocs.  */  external_relocs = (bfd_byte *) malloc (max_output_reloc_count * relsz);  if (external_relocs == NULL && max_output_reloc_count != 0)    {      bfd_set_error (bfd_error_no_memory);      goto error_return;    }  for (o = abfd->sections; o != NULL; o = o->next)    {      struct internal_reloc *irel;      struct internal_reloc *irelend;      struct xcoff_link_hash_entry **rel_hash;      struct xcoff_toc_rel_hash *toc_rel_hash;      bfd_byte *erel;      if (o->reloc_count == 0)	continue;      irel = finfo.section_info[o->target_index].relocs;      irelend = irel + o->reloc_count;      rel_hash = finfo.section_info[o->target_index].rel_hashes;      for (; irel < irelend; irel++, rel_hash++, erel += relsz)	{	  if (*rel_hash != NULL)	    {	      if ((*rel_hash)->indx < 0)		{		  if (! ((*info->callbacks->unattached_reloc)			 (info, (*rel_hash)->root.root.string,			  (bfd *) NULL, o, irel->r_vaddr)))		    goto error_return;		  (*rel_hash)->indx = 0;		}	      irel->r_symndx = (*rel_hash)->indx;	    }	}      for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;	   toc_rel_hash != NULL;	   toc_rel_hash = toc_rel_hash->next)	{	  if (toc_rel_hash->h->u.toc_indx < 0)	    {	      if (! ((*info->callbacks->unattached_reloc)		     (info, toc_rel_hash->h->root.root.string,		      (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))		goto error_return;	      toc_rel_hash->h->u.toc_indx = 0;	    }	  toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;	}      /* XCOFF requires that the relocs be sorted by address.  We tend         to produce them in the order in which their containing csects         appear in the symbol table, which is not necessarily by         address.  So we sort them here.  There may be a better way to         do this.  */      qsort ((PTR) finfo.section_info[o->target_index].relocs,	     o->reloc_count, sizeof (struct internal_reloc),	     xcoff_sort_relocs);      irel = finfo.section_info[o->target_index].relocs;      irelend = irel + o->reloc_count;      erel = external_relocs;      for (; irel < irelend; irel++, rel_hash++, erel += relsz)	bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);      if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0	  || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,			abfd) != relsz * o->reloc_count)	goto error_return;    }  if (external_relocs != NULL)    {      free (external_relocs);      external_relocs = NULL;    }  /* Free up the section information.  */  if (finfo.section_info != NULL)    {      unsigned int i;      for (i = 0; i < abfd->section_count; i++)	{	  if (finfo.section_info[i].relocs != NULL)	    free (finfo.section_info[i].relocs);	  if (finfo.section_info[i].rel_hashes != NULL)	    free (finfo.section_info[i].rel_hashes);	}      free (finfo.section_info);      finfo.section_info = NULL;    }  /* Write out the loader section contents.  */  BFD_ASSERT ((bfd_byte *) finfo.ldrel	      == (xcoff_hash_table (info)->loader_section->contents		  + xcoff_hash_table (info)->ldhdr.l_impoff));  o = xcoff_hash_table (info)->loader_section;  if (! bfd_set_section_contents (abfd, o->output_section,				  o->contents, o->output_offset,				  o->_raw_size))    goto error_return;  /* Write out the magic sections.  */  o = xcoff_hash_table (info)->linkage_section;  if (o->_raw_size > 0      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,				     o->output_offset, o->_raw_size))    goto error_return;  o = xcoff_hash_table (info)->toc_section;  if (o->_raw_size > 0      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,				     o->output_offset, o->_raw_size))    goto error_return;  o = xcoff_hash_table (info)->descriptor_section;  if (o->_raw_size > 0      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,				     o->output_offset, o->_raw_size))    goto error_return;  /* Write out the string table.  */  if (bfd_seek (abfd,		(obj_sym_filepos (abfd)		 + obj_raw_syment_count (abfd) * symesz),		SEEK_SET) != 0)    goto error_return;  bfd_h_put_32 (abfd,		_bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,		(bfd_byte *) strbuf);  if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE)    goto error_return;  if (! _bfd_stringtab_emit (abfd, finfo.strtab))    goto error_return;  _bfd_stringtab_free (finfo.strtab);  /* Write out the debugging string table.  */  o = xcoff_hash_table (info)->debug_section;  if (o != NULL)    {      struct bfd_strtab_hash *debug_strtab;      debug_strtab = xcoff_hash_table (info)->debug_strtab;      BFD_ASSERT (o->output_section->_raw_size - o->output_offset		  >= _bfd_stringtab_size (debug_strtab));      if (bfd_seek (abfd,		    o->output_section->filepos + o->output_offset,		    SEEK_SET) != 0)	goto error_return;      if (! _bfd_stringtab_emit (abfd, debug_strtab))	goto error_return;    }  /* Setting bfd_get_symcount to 0 will cause write_object_contents to     not try to write out the symbols.  */  bfd_get_symcount (abfd) = 0;  return true; error_return:  if (finfo.strtab != NULL)    _bfd_stringtab_free (finfo.strtab);  if (finfo.section_info != NULL)    {      unsigned int i;      for (i = 0; i < abfd->section_count; i++)	{	  if (finfo.section_info[i].relocs != NULL)	    free (finfo.section_info[i].relocs);	  if (finfo.section_info[i].rel_hashes != NULL)	    free (finfo.section_info[i].rel_hashes);	}      free (finfo.section_info);    }  if (finfo.internal_syms != NULL)    free (finfo.internal_syms);  if (finfo.sym_indices != NULL)    free (finfo.sym_indices);  if (finfo.outsyms != NULL)    free (finfo.outsyms);  if (finfo.linenos != NULL)    free (finfo.linenos);  if (finfo.contents != NULL)    free (finfo.contents);  if (finfo.external_relocs != NULL)    free (finfo.external_relocs);  if (external_relocs != NULL)    free (external_relocs);  return false;}