+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ /* We shouldn't unconditionaly mark the TOC section.
+ The output file should only have a TOC if either
+ (a) one of the input files did or (b) we end up
+ creating TOC references as part of the link process. */
+ if (o != xcoff_hash_table (info)->toc_section
+ && (o->flags & SEC_MARK) == 0)
+ {
+ if (! xcoff_mark (info, o))
+ goto error_return;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (entry != NULL
+ && !xcoff_mark_symbol_by_name (info, entry, XCOFF_ENTRY))
+ goto error_return;
+ if (info->init_function != NULL
+ && !xcoff_mark_symbol_by_name (info, info->init_function, 0))
+ goto error_return;
+ if (info->fini_function != NULL
+ && !xcoff_mark_symbol_by_name (info, info->fini_function, 0))
+ goto error_return;
+ if (auto_export_flags != 0)
+ {
+ xcoff_link_hash_traverse (xcoff_hash_table (info),
+ xcoff_mark_auto_exports, &ldinfo);
+ if (ldinfo.failed)
+ goto error_return;
+ }
+ xcoff_sweep (info);
+ xcoff_hash_table (info)->gc = TRUE;
+ }
+
+ /* Return special sections to the caller. */
+ for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
+ {
+ sec = xcoff_hash_table (info)->special_sections[i];
+
+ if (sec != NULL
+ && gc
+ && (sec->flags & SEC_MARK) == 0)
+ sec = NULL;
+
+ special_sections[i] = sec;
+ }
+
+ if (info->input_bfds == NULL)
+ /* I'm not sure what to do in this bizarre case. */
+ return TRUE;
+
+ xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_post_gc_symbol,
+ (void *) &ldinfo);
+ if (ldinfo.failed)
+ goto error_return;
+
+ if (xcoff_hash_table (info)->loader_section
+ && !xcoff_build_loader_section (&ldinfo, libpath))
+ goto error_return;
+
+ /* Allocate space for the magic sections. */
+ sec = xcoff_hash_table (info)->linkage_section;
+ if (sec->size > 0)
+ {
+ sec->contents = bfd_zalloc (output_bfd, sec->size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+ sec = xcoff_hash_table (info)->toc_section;
+ if (sec->size > 0)
+ {
+ sec->contents = bfd_zalloc (output_bfd, sec->size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+ sec = xcoff_hash_table (info)->descriptor_section;
+ if (sec->size > 0)
+ {
+ sec->contents = bfd_zalloc (output_bfd, sec->size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+
+ /* Now that we've done garbage collection, decide which symbols to keep,
+ and figure out the contents of the .debug section. */
+ debug_strtab = xcoff_hash_table (info)->debug_strtab;
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+ {
+ asection *subdeb;
+ bfd_size_type symcount;
+ long *debug_index;
+ asection **csectpp;
+ unsigned int *lineno_counts;
+ struct xcoff_link_hash_entry **sym_hash;
+ bfd_byte *esym, *esymend;
+ bfd_size_type symesz;
+
+ if (sub->xvec != info->output_bfd->xvec)
+ continue;
+
+ if ((sub->flags & DYNAMIC) != 0
+ && !info->static_link)
+ continue;
+
+ if (! _bfd_coff_get_external_symbols (sub))
+ goto error_return;
+
+ symcount = obj_raw_syment_count (sub);
+ debug_index = bfd_zalloc (sub, symcount * sizeof (long));
+ if (debug_index == NULL)
+ goto error_return;
+ xcoff_data (sub)->debug_indices = debug_index;
+
+ if (info->strip == strip_all
+ || info->strip == strip_debugger
+ || info->discard == discard_all)
+ /* We're stripping all debugging information, so there's no need
+ to read SUB's .debug section. */
+ subdeb = NULL;
+ else
+ {
+ /* Grab the contents of SUB's .debug section, if any. */
+ subdeb = bfd_get_section_by_name (sub, ".debug");
+ if (subdeb != NULL && subdeb->size > 0)
+ {
+ /* We use malloc and copy the names into the debug
+ stringtab, rather than bfd_alloc, because I expect
+ that, when linking many files together, many of the
+ strings will be the same. Storing the strings in the
+ hash table should save space in this case. */
+ if (!bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
+ goto error_return;
+ }
+ }
+
+ csectpp = xcoff_data (sub)->csects;
+ lineno_counts = xcoff_data (sub)->lineno_counts;
+ sym_hash = obj_xcoff_sym_hashes (sub);
+ symesz = bfd_coff_symesz (sub);
+ esym = (bfd_byte *) obj_coff_external_syms (sub);
+ esymend = esym + symcount * symesz;
+
+ while (esym < esymend)
+ {
+ struct internal_syment sym;
+ union internal_auxent aux;
+ asection *csect;
+ const char *name;
+ int keep_p;
+
+ bfd_coff_swap_sym_in (sub, esym, &sym);
+
+ /* Read in the csect information, if any. */
+ if (CSECT_SYM_P (sym.n_sclass))
+ {
+ BFD_ASSERT (sym.n_numaux > 0);
+ bfd_coff_swap_aux_in (sub, esym + symesz * sym.n_numaux,
+ sym.n_type, sym.n_sclass,
+ sym.n_numaux - 1, sym.n_numaux, &aux);
+ }
+
+ /* If this symbol's name is stored in the debug section,
+ get a pointer to it. */
+ if (debug_contents != NULL
+ && sym._n._n_n._n_zeroes == 0
+ && bfd_coff_symname_in_debug (sub, &sym))
+ name = (const char *) debug_contents + sym._n._n_n._n_offset;
+ else
+ name = NULL;
+
+ /* Decide whether to copy this symbol to the output file. */
+ csect = *csectpp;
+ keep_p = xcoff_keep_symbol_p (info, sub, &sym, &aux,
+ *sym_hash, csect, name);
+ if (keep_p < 0)
+ return FALSE;
+
+ if (!keep_p)
+ /* Use a debug_index of -2 to record that a symbol should
+ be stripped. */
+ *debug_index = -2;
+ else
+ {
+ /* See whether we should store the symbol name in the
+ output .debug section. */
+ if (name != NULL)
+ {
+ bfd_size_type indx;
+
+ indx = _bfd_stringtab_add (debug_strtab, name, TRUE, TRUE);
+ if (indx == (bfd_size_type) -1)
+ goto error_return;
+ *debug_index = indx;
+ }
+ else
+ *debug_index = -1;
+ if (*sym_hash != 0)
+ (*sym_hash)->flags |= XCOFF_ALLOCATED;
+ if (*lineno_counts > 0)
+ csect->output_section->lineno_count += *lineno_counts;