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