+ if (! aout_link_input_section (flaginfo, input_bfd,
+ obj_textsec (input_bfd),
+ &flaginfo->treloff,
+ exec_hdr (input_bfd)->a_trsize))
+ return FALSE;
+ }
+ if (obj_datasec (input_bfd)->linker_mark)
+ {
+ if (! aout_link_input_section (flaginfo, input_bfd,
+ obj_datasec (input_bfd),
+ &flaginfo->dreloff,
+ exec_hdr (input_bfd)->a_drsize))
+ return FALSE;
+ }
+
+ /* If we are not keeping memory, we don't need the symbols any
+ longer. We still need them if we are keeping memory, because the
+ strings in the hash table point into them. */
+ if (! flaginfo->info->keep_memory)
+ {
+ if (! aout_link_free_symbols (input_bfd))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Do the final link step. This is called on the output BFD. The
+ INFO structure should point to a list of BFDs linked through the
+ link_next field which can be used to find each BFD which takes part
+ in the output. Also, each section in ABFD should point to a list
+ of bfd_link_order structures which list all the input sections for
+ the output section. */
+
+bfd_boolean
+NAME (aout, final_link) (bfd *abfd,
+ struct bfd_link_info *info,
+ void (*callback) (bfd *, file_ptr *, file_ptr *, file_ptr *))
+{
+ struct aout_final_link_info aout_info;
+ bfd_boolean includes_hash_initialized = FALSE;
+ bfd *sub;
+ bfd_size_type trsize, drsize;
+ bfd_size_type max_contents_size;
+ bfd_size_type max_relocs_size;
+ bfd_size_type max_sym_count;
+ bfd_size_type text_size;
+ file_ptr text_end;
+ struct bfd_link_order *p;
+ asection *o;
+ bfd_boolean have_link_order_relocs;
+
+ if (info->shared)
+ abfd->flags |= DYNAMIC;
+
+ aout_info.info = info;
+ aout_info.output_bfd = abfd;
+ aout_info.contents = NULL;
+ aout_info.relocs = NULL;
+ aout_info.symbol_map = NULL;
+ aout_info.output_syms = NULL;
+
+ if (!bfd_hash_table_init_n (&aout_info.includes.root,
+ aout_link_includes_newfunc,
+ sizeof (struct aout_link_includes_entry),
+ 251))
+ goto error_return;
+ includes_hash_initialized = TRUE;
+
+ /* Figure out the largest section size. Also, if generating
+ relocatable output, count the relocs. */
+ trsize = 0;
+ drsize = 0;
+ max_contents_size = 0;
+ max_relocs_size = 0;
+ max_sym_count = 0;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ size_t sz;
+
+ if (info->relocatable)
+ {
+ if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
+ {
+ trsize += exec_hdr (sub)->a_trsize;
+ drsize += exec_hdr (sub)->a_drsize;
+ }
+ else
+ {
+ /* FIXME: We need to identify the .text and .data sections
+ and call get_reloc_upper_bound and canonicalize_reloc to
+ work out the number of relocs needed, and then multiply
+ by the reloc size. */
+ (*_bfd_error_handler)
+ ("%s: relocatable link from %s to %s not supported",
+ bfd_get_filename (abfd),
+ sub->xvec->name, abfd->xvec->name);
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+ }
+
+ if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
+ {
+ sz = obj_textsec (sub)->size;
+ if (sz > max_contents_size)
+ max_contents_size = sz;
+ sz = obj_datasec (sub)->size;
+ if (sz > max_contents_size)
+ max_contents_size = sz;
+
+ sz = exec_hdr (sub)->a_trsize;
+ if (sz > max_relocs_size)
+ max_relocs_size = sz;
+ sz = exec_hdr (sub)->a_drsize;
+ if (sz > max_relocs_size)
+ max_relocs_size = sz;
+
+ sz = obj_aout_external_sym_count (sub);
+ if (sz > max_sym_count)
+ max_sym_count = sz;
+ }
+ }
+
+ if (info->relocatable)
+ {
+ if (obj_textsec (abfd) != NULL)
+ trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
+ ->map_head.link_order)
+ * obj_reloc_entry_size (abfd));
+ if (obj_datasec (abfd) != NULL)
+ drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
+ ->map_head.link_order)
+ * obj_reloc_entry_size (abfd));
+ }
+
+ exec_hdr (abfd)->a_trsize = trsize;
+ exec_hdr (abfd)->a_drsize = drsize;
+ exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
+
+ /* Adjust the section sizes and vmas according to the magic number.
+ This sets a_text, a_data and a_bss in the exec_hdr and sets the
+ filepos for each section. */
+ if (! NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
+ goto error_return;
+
+ /* The relocation and symbol file positions differ among a.out
+ targets. We are passed a callback routine from the backend
+ specific code to handle this.
+ FIXME: At this point we do not know how much space the symbol
+ table will require. This will not work for any (nonstandard)
+ a.out target that needs to know the symbol table size before it
+ can compute the relocation file positions. This may or may not
+ be the case for the hp300hpux target, for example. */
+ (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
+ &aout_info.symoff);
+ obj_textsec (abfd)->rel_filepos = aout_info.treloff;
+ obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
+ obj_sym_filepos (abfd) = aout_info.symoff;
+
+ /* We keep a count of the symbols as we output them. */
+ obj_aout_external_sym_count (abfd) = 0;
+
+ /* We accumulate the string table as we write out the symbols. */
+ aout_info.strtab = _bfd_stringtab_init ();
+ if (aout_info.strtab == NULL)
+ goto error_return;
+
+ /* Allocate buffers to hold section contents and relocs. */
+ aout_info.contents = bfd_malloc (max_contents_size);
+ aout_info.relocs = bfd_malloc (max_relocs_size);
+ aout_info.symbol_map = bfd_malloc (max_sym_count * sizeof (int *));
+ aout_info.output_syms = bfd_malloc ((max_sym_count + 1)
+ * sizeof (struct external_nlist));
+ if ((aout_info.contents == NULL && max_contents_size != 0)
+ || (aout_info.relocs == NULL && max_relocs_size != 0)
+ || (aout_info.symbol_map == NULL && max_sym_count != 0)
+ || aout_info.output_syms == NULL)
+ goto error_return;
+
+ /* If we have a symbol named __DYNAMIC, force it out now. This is
+ required by SunOS. Doing this here rather than in sunos.c is a
+ hack, but it's easier than exporting everything which would be
+ needed. */
+ {
+ struct aout_link_hash_entry *h;
+
+ h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
+ FALSE, FALSE, FALSE);
+ if (h != NULL)
+ aout_link_write_other_symbol (&h->root.root, &aout_info);
+ }
+
+ /* The most time efficient way to do the link would be to read all
+ the input object files into memory and then sort out the
+ information into the output file. Unfortunately, that will
+ probably use too much memory. Another method would be to step
+ through everything that composes the text section and write it
+ out, and then everything that composes the data section and write
+ it out, and then write out the relocs, and then write out the
+ symbols. Unfortunately, that requires reading stuff from each
+ input file several times, and we will not be able to keep all the
+ input files open simultaneously, and reopening them will be slow.
+
+ What we do is basically process one input file at a time. We do
+ everything we need to do with an input file once--copy over the
+ section contents, handle the relocation information, and write
+ out the symbols--and then we throw away the information we read
+ from it. This approach requires a lot of lseeks of the output
+ file, which is unfortunate but still faster than reopening a lot
+ of files.
+
+ We use the output_has_begun field of the input BFDs to see
+ whether we have already handled it. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ sub->output_has_begun = FALSE;
+
+ /* Mark all sections which are to be included in the link. This
+ will normally be every section. We need to do this so that we
+ can identify any sections which the linker has decided to not
+ include. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
+ if (p->type == bfd_indirect_link_order)
+ p->u.indirect.section->linker_mark = TRUE;
+ }
+
+ have_link_order_relocs = FALSE;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->map_head.link_order;
+ p != NULL;
+ p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (p->u.indirect.section->owner)
+ == bfd_target_aout_flavour))
+ {
+ bfd *input_bfd;
+
+ input_bfd = p->u.indirect.section->owner;
+ if (! input_bfd->output_has_begun)
+ {
+ if (! aout_link_input_bfd (&aout_info, input_bfd))
+ goto error_return;
+ input_bfd->output_has_begun = TRUE;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ /* These are handled below. */
+ have_link_order_relocs = TRUE;
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+ /* Write out any symbols that we have not already written out. */
+ bfd_hash_traverse (&info->hash->table,
+ aout_link_write_other_symbol,
+ &aout_info);
+
+ /* Now handle any relocs we were asked to create by the linker.
+ These did not come from any input file. We must do these after
+ we have written out all the symbols, so that we know the symbol
+ indices to use. */
+ if (have_link_order_relocs)
+ {
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->map_head.link_order;
+ p != NULL;
+ p = p->next)
+ {
+ if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! aout_link_reloc_link_order (&aout_info, o, p))
+ goto error_return;
+ }
+ }
+ }
+ }
+
+ if (aout_info.contents != NULL)
+ {
+ free (aout_info.contents);
+ aout_info.contents = NULL;
+ }
+ if (aout_info.relocs != NULL)
+ {
+ free (aout_info.relocs);
+ aout_info.relocs = NULL;
+ }
+ if (aout_info.symbol_map != NULL)
+ {
+ free (aout_info.symbol_map);
+ aout_info.symbol_map = NULL;
+ }
+ if (aout_info.output_syms != NULL)
+ {
+ free (aout_info.output_syms);
+ aout_info.output_syms = NULL;
+ }
+ if (includes_hash_initialized)
+ {
+ bfd_hash_table_free (&aout_info.includes.root);
+ includes_hash_initialized = FALSE;
+ }
+
+ /* Finish up any dynamic linking we may be doing. */
+ if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
+ {
+ if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
+ goto error_return;
+ }