- case strip_none:
- break;
- case strip_debugger:
- if ((type & N_STAB) != 0)
- skip = true;
- break;
- case strip_some:
- if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false)
- == NULL)
- skip = true;
- break;
- case strip_all:
- skip = true;
- break;
- }
- if (skip)
- {
- if (h != (struct aout_link_hash_entry *) NULL)
- h->written = true;
- continue;
- }
-
- /* Get the value of the symbol. */
- if ((type & N_TYPE) == N_TEXT
- || type == N_WEAKT)
- symsec = obj_textsec (input_bfd);
- else if ((type & N_TYPE) == N_DATA
- || type == N_WEAKD)
- symsec = obj_datasec (input_bfd);
- else if ((type & N_TYPE) == N_BSS
- || type == N_WEAKB)
- symsec = obj_bsssec (input_bfd);
- else if ((type & N_TYPE) == N_ABS
- || type == N_WEAKA)
- symsec = bfd_abs_section_ptr;
- else if (((type & N_TYPE) == N_INDR
- && (hresolve == (struct aout_link_hash_entry *) NULL
- || (hresolve->root.type != bfd_link_hash_defined
- && hresolve->root.type != bfd_link_hash_defweak
- && hresolve->root.type != bfd_link_hash_common)))
- || type == N_WARNING)
- {
- /* Pass the next symbol through unchanged. The
- condition above for indirect symbols is so that if
- the indirect symbol was defined, we output it with
- the correct definition so the debugger will
- understand it. */
- pass = true;
- val = GET_WORD (input_bfd, sym->e_value);
- symsec = NULL;
- }
- else if ((type & N_STAB) != 0)
- {
- val = GET_WORD (input_bfd, sym->e_value);
- symsec = NULL;
- }
- else
- {
- /* If we get here with an indirect symbol, it means that
- we are outputting it with a real definition. In such
- a case we do not want to output the next symbol,
- which is the target of the indirection. */
- if ((type & N_TYPE) == N_INDR)
- skip_next = true;
-
- symsec = NULL;
-
- /* We need to get the value from the hash table. We use
- hresolve so that if we have defined an indirect
- symbol we output the final definition. */
- if (h == (struct aout_link_hash_entry *) NULL)
- {
- switch (type & N_TYPE)
- {
- case N_SETT:
- symsec = obj_textsec (input_bfd);
- break;
- case N_SETD:
- symsec = obj_datasec (input_bfd);
- break;
- case N_SETB:
- symsec = obj_bsssec (input_bfd);
- break;
- case N_SETA:
- symsec = bfd_abs_section_ptr;
- break;
- default:
- val = 0;
- break;
- }
- }
- else if (hresolve->root.type == bfd_link_hash_defined
- || hresolve->root.type == bfd_link_hash_defweak)
- {
- asection *input_section;
- asection *output_section;
-
- /* This case usually means a common symbol which was
- turned into a defined symbol. */
- input_section = hresolve->root.u.def.section;
- output_section = input_section->output_section;
- BFD_ASSERT (bfd_is_abs_section (output_section)
- || output_section->owner == output_bfd);
- val = (hresolve->root.u.def.value
- + bfd_get_section_vma (output_bfd, output_section)
- + input_section->output_offset);
-
- /* Get the correct type based on the section. If
- this is a constructed set, force it to be
- globally visible. */
- if (type == N_SETT
- || type == N_SETD
- || type == N_SETB
- || type == N_SETA)
- type |= N_EXT;
-
- type &=~ N_TYPE;
-
- if (output_section == obj_textsec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_TEXT
- : N_WEAKT);
- else if (output_section == obj_datasec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_DATA
- : N_WEAKD);
- else if (output_section == obj_bsssec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_BSS
- : N_WEAKB);
- else
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_ABS
- : N_WEAKA);
- }
- else if (hresolve->root.type == bfd_link_hash_common)
- val = hresolve->root.u.c.size;
- else if (hresolve->root.type == bfd_link_hash_undefweak)
- {
- val = 0;
- type = N_WEAKU;
- }
- else
- val = 0;
- }
- if (symsec != (asection *) NULL)
- val = (symsec->output_section->vma
- + symsec->output_offset
- + (GET_WORD (input_bfd, sym->e_value)
- - symsec->vma));
-
- /* If this is a global symbol set the written flag, and if
- it is a local symbol see if we should discard it. */
- if (h != (struct aout_link_hash_entry *) NULL)
- {
- h->written = true;
- h->indx = obj_aout_external_sym_count (output_bfd);
- }
- else if ((type & N_TYPE) != N_SETT
- && (type & N_TYPE) != N_SETD
- && (type & N_TYPE) != N_SETB
- && (type & N_TYPE) != N_SETA)
- {
- switch (discard)
- {
- case discard_none:
- case discard_sec_merge:
- break;
- case discard_l:
- if ((type & N_STAB) == 0
- && bfd_is_local_label_name (input_bfd, name))
- skip = true;
- break;
- case discard_all:
- skip = true;
- break;
- }
- if (skip)
- {
- pass = false;
- continue;
- }
- }
-
- /* An N_BINCL symbol indicates the start of the stabs
- entries for a header file. We need to scan ahead to the
- next N_EINCL symbol, ignoring nesting, adding up all the
- characters in the symbol names, not including the file
- numbers in types (the first number after an open
- parenthesis). */
- if (type == N_BINCL)
- {
- struct external_nlist *incl_sym;
- int nest;
- struct aout_link_includes_entry *incl_entry;
- struct aout_link_includes_totals *t;
-
- val = 0;
- nest = 0;
- for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
- {
- int incl_type;
-
- incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
- if (incl_type == N_EINCL)
- {
- if (nest == 0)
- break;
- --nest;
- }
- else if (incl_type == N_BINCL)
- ++nest;
- else if (nest == 0)
- {
- const char *s;
-
- s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
- for (; *s != '\0'; s++)
- {
- val += *s;
- if (*s == '(')
- {
- /* Skip the file number. */
- ++s;
- while (isdigit ((unsigned char) *s))
- ++s;
- --s;
- }
- }
- }
- }
-
- /* If we have already included a header file with the
- same value, then replace this one with an N_EXCL
- symbol. */
- copy = ! finfo->info->keep_memory;
- incl_entry = aout_link_includes_lookup (&finfo->includes,
- name, true, copy);
- if (incl_entry == NULL)
- return false;
- for (t = incl_entry->totals; t != NULL; t = t->next)
- if (t->total == val)
- break;
- if (t == NULL)
- {
- /* This is the first time we have seen this header
- file with this set of stabs strings. */
- t = ((struct aout_link_includes_totals *)
- bfd_hash_allocate (&finfo->includes.root,
- sizeof *t));
- if (t == NULL)
- return false;
- t->total = val;
- t->next = incl_entry->totals;
- incl_entry->totals = t;
- }
- else
- {
- int *incl_map;
-
- /* This is a duplicate header file. We must change
- it to be an N_EXCL entry, and mark all the
- included symbols to prevent outputting them. */
- type = N_EXCL;
-
- nest = 0;
- for (incl_sym = sym + 1, incl_map = symbol_map + 1;
- incl_sym < sym_end;
- incl_sym++, incl_map++)
- {
- int incl_type;
-
- incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
- if (incl_type == N_EINCL)
- {
- if (nest == 0)
- {
- *incl_map = -1;
- break;
- }
- --nest;
- }
- else if (incl_type == N_BINCL)
- ++nest;
- else if (nest == 0)
- *incl_map = -1;
- }
- }
- }
- }
-
- /* Copy this symbol into the list of symbols we are going to
- write out. */
- bfd_h_put_8 (output_bfd, type, outsym->e_type);
- bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other),
- outsym->e_other);
- bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc),
- outsym->e_desc);
- copy = false;
- if (! finfo->info->keep_memory)
- {
- /* name points into a string table which we are going to
- free. If there is a hash table entry, use that string.
- Otherwise, copy name into memory. */
- if (h != (struct aout_link_hash_entry *) NULL)
- name = h->root.root.string;
- else
- copy = true;
- }
- strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
- name, copy);
- if (strtab_index == (bfd_size_type) -1)
- return false;
- PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
- PUT_WORD (output_bfd, val, outsym->e_value);
- *symbol_map = obj_aout_external_sym_count (output_bfd);
- ++obj_aout_external_sym_count (output_bfd);
- ++outsym;
- }
-
- /* Write out the output symbols we have just constructed. */
- if (outsym > finfo->output_syms)
- {
- bfd_size_type outsym_count;
-
- if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
- return false;
- outsym_count = outsym - finfo->output_syms;
- if (bfd_write ((PTR) finfo->output_syms,
- (bfd_size_type) EXTERNAL_NLIST_SIZE,
- (bfd_size_type) outsym_count, output_bfd)
- != outsym_count * EXTERNAL_NLIST_SIZE)
- return false;
- finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE;
- }
-
- return true;
-}
-
-/* Write out a symbol that was not associated with an a.out input
- object. */
-
-static boolean
-aout_link_write_other_symbol (h, data)
- struct aout_link_hash_entry *h;
- PTR data;
-{
- struct aout_final_link_info *finfo = (struct aout_final_link_info *) data;
- bfd *output_bfd;
- int type;
- bfd_vma val;
- struct external_nlist outsym;
- bfd_size_type indx;
-
- output_bfd = finfo->output_bfd;
-
- if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
- {
- if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
- (output_bfd, finfo->info, h)))
- {
- /* FIXME: No way to handle errors. */
- abort ();
- }
- }
-
- if (h->written)
- return true;
-
- h->written = true;
-
- /* An indx of -2 means the symbol must be written. */
- if (h->indx != -2
- && (finfo->info->strip == strip_all
- || (finfo->info->strip == strip_some
- && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
- false, false) == NULL)))
- return true;
-
- switch (h->root.type)
- {
- default:
- abort ();
- /* Avoid variable not initialized warnings. */
- return true;
- case bfd_link_hash_new:
- /* This can happen for set symbols when sets are not being
- built. */
- return true;
- case bfd_link_hash_undefined:
- type = N_UNDF | N_EXT;
- val = 0;
- break;
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- {
- asection *sec;
-
- sec = h->root.u.def.section->output_section;
- BFD_ASSERT (bfd_is_abs_section (sec)
- || sec->owner == output_bfd);
- if (sec == obj_textsec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
- else if (sec == obj_datasec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
- else if (sec == obj_bsssec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
- else
- type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
- type |= N_EXT;
- val = (h->root.u.def.value
- + sec->vma
- + h->root.u.def.section->output_offset);
- }
- break;
- case bfd_link_hash_common:
- type = N_UNDF | N_EXT;
- val = h->root.u.c.size;
- break;
- case bfd_link_hash_undefweak:
- type = N_WEAKU;
- val = 0;
- case bfd_link_hash_indirect:
- case bfd_link_hash_warning:
- /* FIXME: Ignore these for now. The circumstances under which
- they should be written out are not clear to me. */
- return true;
- }
-
- bfd_h_put_8 (output_bfd, type, outsym.e_type);
- bfd_h_put_8 (output_bfd, 0, outsym.e_other);
- bfd_h_put_16 (output_bfd, 0, outsym.e_desc);
- indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
- false);
- if (indx == (bfd_size_type) -1)
- {
- /* FIXME: No way to handle errors. */
- abort ();
- }
- PUT_WORD (output_bfd, indx, outsym.e_strx);
- PUT_WORD (output_bfd, val, outsym.e_value);
-
- if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
- || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE,
- (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE)
- {
- /* FIXME: No way to handle errors. */
- abort ();
- }
-
- finfo->symoff += EXTERNAL_NLIST_SIZE;
- h->indx = obj_aout_external_sym_count (output_bfd);
- ++obj_aout_external_sym_count (output_bfd);
-
- return true;
-}
-
-/* Link an a.out section into the output file. */
-
-static boolean
-aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
- rel_size)
- struct aout_final_link_info *finfo;
- bfd *input_bfd;
- asection *input_section;
- file_ptr *reloff_ptr;
- bfd_size_type rel_size;
-{
- bfd_size_type input_size;
- PTR relocs;