Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Typedefs | Functions
libcoff-in.h File Reference
#include "bfdlink.h"

Go to the source code of this file.

Classes

struct  coff_tdata
struct  pe_tdata
struct  xcoff_tdata
struct  coff_section_tdata
struct  xcoff_section_tdata
struct  pei_section_tdata
struct  coff_link_hash_entry
struct  coff_debug_merge_element
struct  coff_debug_merge_type
struct  coff_debug_merge_hash_entry
struct  coff_debug_merge_hash_table
struct  coff_section_alignment_entry

Defines

#define coff_data(bfd)   ((bfd)->tdata.coff_obj_data)
#define exec_hdr(bfd)   (coff_data (bfd)->hdr)
#define obj_pe(bfd)   (coff_data (bfd)->pe)
#define obj_symbols(bfd)   (coff_data (bfd)->symbols)
#define obj_sym_filepos(bfd)   (coff_data (bfd)->sym_filepos)
#define obj_relocbase(bfd)   (coff_data (bfd)->relocbase)
#define obj_raw_syments(bfd)   (coff_data (bfd)->raw_syments)
#define obj_raw_syment_count(bfd)   (coff_data (bfd)->raw_syment_count)
#define obj_convert(bfd)   (coff_data (bfd)->conversion_table)
#define obj_conv_table_size(bfd)   (coff_data (bfd)->conv_table_size)
#define obj_coff_external_syms(bfd)   (coff_data (bfd)->external_syms)
#define obj_coff_keep_syms(bfd)   (coff_data (bfd)->keep_syms)
#define obj_coff_strings(bfd)   (coff_data (bfd)->strings)
#define obj_coff_keep_strings(bfd)   (coff_data (bfd)->keep_strings)
#define obj_coff_sym_hashes(bfd)   (coff_data (bfd)->sym_hashes)
#define obj_coff_strings_written(bfd)   (coff_data (bfd)->strings_written)
#define obj_coff_local_toc_table(bfd)   (coff_data (bfd)->local_toc_sym_map)
#define pe_data(bfd)   ((bfd)->tdata.pe_obj_data)
#define xcoff_data(abfd)   ((abfd)->tdata.xcoff_obj_data)
#define coffsymbol(asymbol)   ((coff_symbol_type *)(&((asymbol)->the_bfd)))
#define coff_section_data(abfd, sec)   ((struct coff_section_tdata *) (sec)->used_by_bfd)
#define xcoff_section_data(abfd, sec)   ((struct xcoff_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
#define pei_section_data(abfd, sec)   ((struct pei_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
#define COFF_LINK_HASH_PE_SECTION_SYMBOL   (01)
#define coff_link_hash_lookup(table, string, create, copy, follow)
#define coff_link_hash_traverse(table, func, info)
#define coff_hash_table(p)   ((struct coff_link_hash_table *) ((p)->hash))
#define STRING_SIZE_SIZE   4
#define coff_debug_merge_hash_table_init(table)
#define coff_debug_merge_hash_table_free(table)   (bfd_hash_table_free (&(table)->root))
#define coff_debug_merge_hash_lookup(table, string, create, copy)
#define COFF_SECTION_NAME_EXACT_MATCH(name)   (name), ((unsigned int) -1)
#define COFF_SECTION_NAME_PARTIAL_MATCH(name)   (name), (sizeof (name) - 1)
#define COFF_ALIGNMENT_FIELD_EMPTY   ((unsigned int) -1)
#define coff_get_section_contents_in_window   _bfd_generic_get_section_contents_in_window

Typedefs

typedef struct coff_tdata coff_data_type
typedef struct pe_tdata pe_data_type

Functions

const bfd_targetcoff_object_p (bfd *)
struct bfd_sectioncoff_section_from_bfd_index (bfd *, int)
long coff_get_symtab_upper_bound (bfd *)
long coff_canonicalize_symtab (bfd *, asymbol **)
int coff_count_linenumbers (bfd *)
struct coff_symbol_structcoff_symbol_from (bfd *, asymbol *)
bfd_boolean coff_renumber_symbols (bfd *, int *)
void coff_mangle_symbols (bfd *)
bfd_boolean coff_write_symbols (bfd *)
bfd_boolean coff_write_linenumbers (bfd *)
alentcoff_get_lineno (bfd *, asymbol *)
asymbolcoff_section_symbol (bfd *, char *)
bfd_boolean _bfd_coff_get_external_symbols (bfd *)
const char * _bfd_coff_read_string_table (bfd *)
bfd_boolean _bfd_coff_free_symbols (bfd *)
struct coff_ptr_structcoff_get_normalized_symtab (bfd *)
long coff_get_reloc_upper_bound (bfd *, sec_ptr)
asymbolcoff_make_empty_symbol (bfd *)
void coff_print_symbol (bfd *, void *filep, asymbol *, bfd_print_symbol_type)
void coff_get_symbol_info (bfd *, asymbol *, symbol_info *ret)
bfd_boolean _bfd_coff_is_local_label_name (bfd *, const char *)
asymbolcoff_bfd_make_debug_symbol (bfd *, void *, unsigned long)
bfd_boolean coff_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *)
bfd_boolean coff_find_inliner_info (bfd *, const char **, const char **, unsigned int *)
int coff_sizeof_headers (bfd *, struct bfd_link_info *)
bfd_boolean bfd_coff_reloc16_relax_section (bfd *, asection *, struct bfd_link_info *, bfd_boolean *)
bfd_bytebfd_coff_reloc16_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **)
bfd_vma bfd_coff_reloc16_get_value (arelent *, struct bfd_link_info *, asection *)
void bfd_perform_slip (bfd *, unsigned int, asection *, bfd_vma)
struct bfd_hash_entry_bfd_coff_link_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *)
bfd_boolean _bfd_coff_link_hash_table_init (struct coff_link_hash_table *, bfd *, struct bfd_hash_entry *(*)(struct bfd_hash_entry *, struct bfd_hash_table *, const char *), unsigned int)
struct bfd_link_hash_table_bfd_coff_link_hash_table_create (bfd *)
const char * _bfd_coff_internal_syment_name (bfd *, const struct internal_syment *, char *)
bfd_boolean _bfd_coff_link_add_symbols (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_coff_final_link (bfd *, struct bfd_link_info *)
struct internal_reloc_bfd_coff_read_internal_relocs (bfd *, asection *, bfd_boolean, bfd_byte *, bfd_boolean, struct internal_reloc *)
bfd_boolean _bfd_coff_generic_relocate_section (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **)
struct bfd_hash_entry_bfd_coff_debug_merge_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *)
bfd_boolean _bfd_coff_write_global_sym (struct coff_link_hash_entry *, void *)
bfd_boolean _bfd_coff_write_task_globals (struct coff_link_hash_entry *, void *)
bfd_boolean _bfd_coff_link_input_bfd (struct coff_final_link_info *, bfd *)
bfd_boolean _bfd_coff_reloc_link_order (bfd *, struct coff_final_link_info *, asection *, struct bfd_link_order *)
long _bfd_xcoff_get_dynamic_symtab_upper_bound (bfd *)
long _bfd_xcoff_canonicalize_dynamic_symtab (bfd *, asymbol **)
long _bfd_xcoff_get_dynamic_reloc_upper_bound (bfd *)
long _bfd_xcoff_canonicalize_dynamic_reloc (bfd *, arelent **, asymbol **)
struct bfd_link_hash_table_bfd_xcoff_bfd_link_hash_table_create (bfd *)
void _bfd_xcoff_bfd_link_hash_table_free (struct bfd_link_hash_table *)
bfd_boolean _bfd_xcoff_bfd_link_add_symbols (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_xcoff_bfd_final_link (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_ppc_xcoff_relocate_section (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **)
bfd_boolean ppc_allocate_toc_section (struct bfd_link_info *)
bfd_boolean ppc_process_before_allocation (bfd *, struct bfd_link_info *)

Class Documentation

struct coff_tdata

Definition at line 47 of file libcoff-in.h.

Collaboration diagram for coff_tdata:
Class Members
int conv_table_size
unsigned int * conversion_table
void * dwarf2_find_line_info
void * external_syms
flagword flags
bfd_boolean keep_strings
bfd_boolean keep_syms
void * line_info
struct bfd_link_info * link_info
unsigned local_auxesz
unsigned local_linesz
unsigned local_n_btmask
unsigned local_n_btshft
unsigned local_n_tmask
unsigned local_n_tshift
unsigned local_symesz
int * local_toc_sym_map
int pe
unsigned long raw_syment_count
struct coff_ptr_struct * raw_syments
long int relocbase
char * strings
bfd_boolean strings_written
file_ptr sym_filepos
struct coff_link_hash_entry ** sym_hashes
struct coff_symbol_struct * symbols
long timestamp
struct xcoff_tdata

Definition at line 127 of file libcoff-in.h.

Collaboration diagram for xcoff_tdata:
Class Members
coff_data_type coff
short cputype
asection ** csects
int data_align_power
unsigned long * debug_indices
bfd_boolean full_aouthdr
unsigned int import_file_id
bfd_vma maxdata
bfd_vma maxstack
short modtype
int snentry
int sntoc
int text_align_power
bfd_vma toc
bfd_boolean xcoff64
struct coff_section_tdata

Definition at line 180 of file libcoff-in.h.

Collaboration diagram for coff_section_tdata:
Class Members
struct coff_comdat_info * comdat
bfd_byte * contents
const char * function
unsigned int i
bfd_boolean keep_contents
bfd_boolean keep_relocs
int line_base
bfd_vma offset
struct internal_reloc * relocs
void * stab_info
void * tdata
struct xcoff_section_tdata

Definition at line 209 of file libcoff-in.h.

Collaboration diagram for xcoff_section_tdata:
Class Members
asection * enclosing
unsigned long first_symndx
unsigned long last_symndx
unsigned int lineno_count
struct pei_section_tdata

Definition at line 229 of file libcoff-in.h.

Class Members
long pe_flags
bfd_size_type virt_size
struct coff_link_hash_entry

Definition at line 243 of file libcoff-in.h.

Collaboration diagram for coff_link_hash_entry:
Class Members
union internal_auxent * aux
bfd * auxbfd
unsigned char class
unsigned short coff_link_hash_flags
long indx
char numaux
unsigned short type
struct coff_link_hash_table

Definition at line 274 of file libcoff-in.h.

struct coff_debug_merge_element

Definition at line 372 of file libcoff-in.h.

Collaboration diagram for coff_debug_merge_element:
Class Members
const char * name
struct coff_debug_merge_element * next
long tagndx
unsigned int type
struct coff_debug_merge_type

Definition at line 389 of file libcoff-in.h.

Collaboration diagram for coff_debug_merge_type:
Class Members
int class
struct coff_debug_merge_element * elements
long indx
struct coff_debug_merge_type * next
struct coff_debug_merge_hash_entry

Definition at line 406 of file libcoff-in.h.

Collaboration diagram for coff_debug_merge_hash_entry:
Class Members
struct coff_debug_merge_type * types
struct coff_debug_merge_hash_table

Definition at line 416 of file libcoff-in.h.

struct coff_link_section_info

Definition at line 441 of file libcoff-in.h.

Collaboration diagram for coff_link_section_info:
Class Members
struct coff_link_hash_entry ** rel_hashes
struct internal_reloc * relocs
struct coff_final_link_info

Definition at line 452 of file libcoff-in.h.

Collaboration diagram for coff_final_link_info:
Class Members
bfd_byte * contents
bfd_byte * external_relocs
bfd_boolean failed
bfd_boolean global_to_static
struct bfd_link_info * info
struct internal_reloc * internal_relocs
struct internal_syment * internal_syms
long last_bf_index
long last_file_index
bfd_byte * linenos
bfd * output_bfd
bfd_byte * outsyms
asection ** sec_ptrs
struct coff_link_section_info * section_info
struct bfd_strtab_hash * strtab
long * sym_indices
struct coff_section_alignment_entry

Definition at line 504 of file libcoff-in.h.

Class Members
unsigned int alignment_power
unsigned int comparison_length
unsigned int default_alignment_max
unsigned int default_alignment_min
const char * name

Define Documentation

Definition at line 529 of file libcoff-in.h.

#define coff_data (   bfd)    ((bfd)->tdata.coff_obj_data)

Definition at line 27 of file libcoff-in.h.

#define coff_debug_merge_hash_lookup (   table,
  string,
  create,
  copy 
)
Value:
((struct coff_debug_merge_hash_entry *) \
   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))

Definition at line 434 of file libcoff-in.h.

#define coff_debug_merge_hash_table_free (   table)    (bfd_hash_table_free (&(table)->root))

Definition at line 429 of file libcoff-in.h.

#define coff_debug_merge_hash_table_init (   table)
Value:

Definition at line 423 of file libcoff-in.h.

Definition at line 570 of file libcoff-in.h.

#define coff_hash_table (   p)    ((struct coff_link_hash_table *) ((p)->hash))

Definition at line 298 of file libcoff-in.h.

#define coff_link_hash_lookup (   table,
  string,
  create,
  copy,
  follow 
)
Value:
((struct coff_link_hash_entry *)                               \
   bfd_link_hash_lookup (&(table)->root, (string), (create),          \
                      (copy), (follow)))

Definition at line 283 of file libcoff-in.h.

Definition at line 269 of file libcoff-in.h.

#define coff_link_hash_traverse (   table,
  func,
  info 
)
Value:
(bfd_link_hash_traverse                                        \
   (&(table)->root,                                            \
    (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
    (info)))

Definition at line 290 of file libcoff-in.h.

#define coff_section_data (   abfd,
  sec 
)    ((struct coff_section_tdata *) (sec)->used_by_bfd)

Definition at line 204 of file libcoff-in.h.

#define COFF_SECTION_NAME_EXACT_MATCH (   name)    (name), ((unsigned int) -1)

Definition at line 516 of file libcoff-in.h.

#define COFF_SECTION_NAME_PARTIAL_MATCH (   name)    (name), (sizeof (name) - 1)

Definition at line 517 of file libcoff-in.h.

#define coffsymbol (   asymbol)    ((coff_symbol_type *)(&((asymbol)->the_bfd)))

Definition at line 175 of file libcoff-in.h.

#define exec_hdr (   bfd)    (coff_data (bfd)->hdr)

Definition at line 28 of file libcoff-in.h.

#define obj_coff_external_syms (   bfd)    (coff_data (bfd)->external_syms)

Definition at line 37 of file libcoff-in.h.

#define obj_coff_keep_strings (   bfd)    (coff_data (bfd)->keep_strings)

Definition at line 40 of file libcoff-in.h.

#define obj_coff_keep_syms (   bfd)    (coff_data (bfd)->keep_syms)

Definition at line 38 of file libcoff-in.h.

#define obj_coff_local_toc_table (   bfd)    (coff_data (bfd)->local_toc_sym_map)

Definition at line 43 of file libcoff-in.h.

#define obj_coff_strings (   bfd)    (coff_data (bfd)->strings)

Definition at line 39 of file libcoff-in.h.

#define obj_coff_strings_written (   bfd)    (coff_data (bfd)->strings_written)

Definition at line 42 of file libcoff-in.h.

#define obj_coff_sym_hashes (   bfd)    (coff_data (bfd)->sym_hashes)

Definition at line 41 of file libcoff-in.h.

#define obj_conv_table_size (   bfd)    (coff_data (bfd)->conv_table_size)

Definition at line 36 of file libcoff-in.h.

#define obj_convert (   bfd)    (coff_data (bfd)->conversion_table)

Definition at line 35 of file libcoff-in.h.

#define obj_pe (   bfd)    (coff_data (bfd)->pe)

Definition at line 29 of file libcoff-in.h.

#define obj_raw_syment_count (   bfd)    (coff_data (bfd)->raw_syment_count)

Definition at line 34 of file libcoff-in.h.

#define obj_raw_syments (   bfd)    (coff_data (bfd)->raw_syments)

Definition at line 33 of file libcoff-in.h.

#define obj_relocbase (   bfd)    (coff_data (bfd)->relocbase)

Definition at line 32 of file libcoff-in.h.

#define obj_sym_filepos (   bfd)    (coff_data (bfd)->sym_filepos)

Definition at line 31 of file libcoff-in.h.

#define obj_symbols (   bfd)    (coff_data (bfd)->symbols)

Definition at line 30 of file libcoff-in.h.

#define pe_data (   bfd)    ((bfd)->tdata.pe_obj_data)

Definition at line 123 of file libcoff-in.h.

#define pei_section_data (   abfd,
  sec 
)    ((struct pei_section_tdata *) coff_section_data ((abfd), (sec))->tdata)

Definition at line 238 of file libcoff-in.h.

#define STRING_SIZE_SIZE   4

Definition at line 364 of file libcoff-in.h.

#define xcoff_data (   abfd)    ((abfd)->tdata.xcoff_obj_data)

Definition at line 171 of file libcoff-in.h.

#define xcoff_section_data (   abfd,
  sec 
)    ((struct xcoff_section_tdata *) coff_section_data ((abfd), (sec))->tdata)

Definition at line 224 of file libcoff-in.h.


Typedef Documentation


Function Documentation

Definition at line 129 of file cofflink.c.

{
  struct coff_debug_merge_hash_entry *ret =
    (struct coff_debug_merge_hash_entry *) entry;

  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
  if (ret == (struct coff_debug_merge_hash_entry *) NULL)
    ret = ((struct coff_debug_merge_hash_entry *)
          bfd_hash_allocate (table,
                           sizeof (struct coff_debug_merge_hash_entry)));
  if (ret == (struct coff_debug_merge_hash_entry *) NULL)
    return (struct bfd_hash_entry *) ret;

  /* Call the allocation method of the superclass.  */
  ret = ((struct coff_debug_merge_hash_entry *)
        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
  if (ret != (struct coff_debug_merge_hash_entry *) NULL)
    {
      /* Set local fields.  */
      ret->types = NULL;
    }

  return (struct bfd_hash_entry *) ret;
}

Definition at line 626 of file cofflink.c.

{
  bfd_size_type symesz;
  struct coff_final_link_info finfo;
  bfd_boolean debug_merge_allocated;
  bfd_boolean long_section_names;
  asection *o;
  struct bfd_link_order *p;
  bfd_size_type max_sym_count;
  bfd_size_type max_lineno_count;
  bfd_size_type max_reloc_count;
  bfd_size_type max_output_reloc_count;
  bfd_size_type max_contents_size;
  file_ptr rel_filepos;
  unsigned int relsz;
  file_ptr line_filepos;
  unsigned int linesz;
  bfd *sub;
  bfd_byte *external_relocs = NULL;
  char strbuf[STRING_SIZE_SIZE];
  bfd_size_type amt;

  symesz = bfd_coff_symesz (abfd);

  finfo.info = info;
  finfo.output_bfd = abfd;
  finfo.strtab = NULL;
  finfo.section_info = NULL;
  finfo.last_file_index = -1;
  finfo.last_bf_index = -1;
  finfo.internal_syms = NULL;
  finfo.sec_ptrs = NULL;
  finfo.sym_indices = NULL;
  finfo.outsyms = NULL;
  finfo.linenos = NULL;
  finfo.contents = NULL;
  finfo.external_relocs = NULL;
  finfo.internal_relocs = NULL;
  finfo.global_to_static = FALSE;
  debug_merge_allocated = FALSE;

  coff_data (abfd)->link_info = info;

  finfo.strtab = _bfd_stringtab_init ();
  if (finfo.strtab == NULL)
    goto error_return;

  if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
    goto error_return;
  debug_merge_allocated = TRUE;

  /* Compute the file positions for all the sections.  */
  if (! abfd->output_has_begun)
    {
      if (! bfd_coff_compute_section_file_positions (abfd))
       goto error_return;
    }

  /* Count the line numbers and relocation entries required for the
     output file.  Set the file positions for the relocs.  */
  rel_filepos = obj_relocbase (abfd);
  relsz = bfd_coff_relsz (abfd);
  max_contents_size = 0;
  max_lineno_count = 0;
  max_reloc_count = 0;

  long_section_names = FALSE;
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      o->reloc_count = 0;
      o->lineno_count = 0;
      for (p = o->map_head.link_order; p != NULL; p = p->next)
       {
         if (p->type == bfd_indirect_link_order)
           {
             asection *sec;

             sec = p->u.indirect.section;

             /* 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.  */
             sec->linker_mark = TRUE;

             if (info->strip == strip_none
                || info->strip == strip_some)
              o->lineno_count += sec->lineno_count;

             if (info->relocatable)
              o->reloc_count += sec->reloc_count;

             if (sec->rawsize > max_contents_size)
              max_contents_size = sec->rawsize;
             if (sec->size > max_contents_size)
              max_contents_size = sec->size;
             if (sec->lineno_count > max_lineno_count)
              max_lineno_count = sec->lineno_count;
             if (sec->reloc_count > max_reloc_count)
              max_reloc_count = sec->reloc_count;
           }
         else if (info->relocatable
                 && (p->type == bfd_section_reloc_link_order
                     || p->type == bfd_symbol_reloc_link_order))
           ++o->reloc_count;
       }
      if (o->reloc_count == 0)
       o->rel_filepos = 0;
      else
       {
         o->flags |= SEC_RELOC;
         o->rel_filepos = rel_filepos;
         rel_filepos += o->reloc_count * relsz;
         /* In PE COFF, if there are at least 0xffff relocations an
            extra relocation will be written out to encode the count.  */
         if (obj_pe (abfd) && o->reloc_count >= 0xffff)
           rel_filepos += relsz;
       }

      if (bfd_coff_long_section_names (abfd)
         && strlen (o->name) > SCNNMLEN)
       {
         /* This section has a long name which must go in the string
             table.  This must correspond to the code in
             coff_write_object_contents which puts the string index
             into the s_name field of the section header.  That is why
             we pass hash as FALSE.  */
         if (_bfd_stringtab_add (finfo.strtab, o->name, FALSE, FALSE)
             == (bfd_size_type) -1)
           goto error_return;
         long_section_names = TRUE;
       }
    }

  /* If doing a relocatable link, allocate space for the pointers we
     need to keep.  */
  if (info->relocatable)
    {
      unsigned int i;

      /* We use section_count + 1, rather than section_count, because
         the target_index fields are 1 based.  */
      amt = abfd->section_count + 1;
      amt *= sizeof (struct coff_link_section_info);
      finfo.section_info = bfd_malloc (amt);
      if (finfo.section_info == NULL)
       goto error_return;
      for (i = 0; i <= abfd->section_count; i++)
       {
         finfo.section_info[i].relocs = NULL;
         finfo.section_info[i].rel_hashes = NULL;
       }
    }

  /* We now know the size of the relocs, so we can determine the file
     positions of the line numbers.  */
  line_filepos = rel_filepos;
  linesz = bfd_coff_linesz (abfd);
  max_output_reloc_count = 0;
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (o->lineno_count == 0)
       o->line_filepos = 0;
      else
       {
         o->line_filepos = line_filepos;
         line_filepos += o->lineno_count * linesz;
       }

      if (o->reloc_count != 0)
       {
         /* We don't know the indices of global symbols until we have
             written out all the local symbols.  For each section in
             the output file, we keep an array of pointers to hash
             table entries.  Each entry in the array corresponds to a
             reloc.  When we find a reloc against a global symbol, we
             set the corresponding entry in this array so that we can
             fix up the symbol index after we have written out all the
             local symbols.

            Because of this problem, we also keep the relocs in
            memory until the end of the link.  This wastes memory,
            but only when doing a relocatable link, which is not the
            common case.  */
         BFD_ASSERT (info->relocatable);
         amt = o->reloc_count;
         amt *= sizeof (struct internal_reloc);
         finfo.section_info[o->target_index].relocs = bfd_malloc (amt);
         amt = o->reloc_count;
         amt *= sizeof (struct coff_link_hash_entry *);
         finfo.section_info[o->target_index].rel_hashes = bfd_malloc (amt);
         if (finfo.section_info[o->target_index].relocs == NULL
             || finfo.section_info[o->target_index].rel_hashes == NULL)
           goto error_return;

         if (o->reloc_count > max_output_reloc_count)
           max_output_reloc_count = o->reloc_count;
       }

      /* Reset the reloc and lineno counts, so that we can use them to
        count the number of entries we have output so far.  */
      o->reloc_count = 0;
      o->lineno_count = 0;
    }

  obj_sym_filepos (abfd) = line_filepos;

  /* Figure out the largest number of symbols in an input BFD.  Take
     the opportunity to clear the output_has_begun fields of all the
     input BFD's.  */
  max_sym_count = 0;
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
    {
      size_t sz;

      sub->output_has_begun = FALSE;
      sz = obj_raw_syment_count (sub);
      if (sz > max_sym_count)
       max_sym_count = sz;
    }

  /* Allocate some buffers used while linking.  */
  amt = max_sym_count * sizeof (struct internal_syment);
  finfo.internal_syms = bfd_malloc (amt);
  amt = max_sym_count * sizeof (asection *);
  finfo.sec_ptrs = bfd_malloc (amt);
  amt = max_sym_count * sizeof (long);
  finfo.sym_indices = bfd_malloc (amt);
  finfo.outsyms = bfd_malloc ((max_sym_count + 1) * symesz);
  amt = max_lineno_count * bfd_coff_linesz (abfd);
  finfo.linenos = bfd_malloc (amt);
  finfo.contents = bfd_malloc (max_contents_size);
  amt = max_reloc_count * relsz;
  finfo.external_relocs = bfd_malloc (amt);
  if (! info->relocatable)
    {
      amt = max_reloc_count * sizeof (struct internal_reloc);
      finfo.internal_relocs = bfd_malloc (amt);
    }
  if ((finfo.internal_syms == NULL && max_sym_count > 0)
      || (finfo.sec_ptrs == NULL && max_sym_count > 0)
      || (finfo.sym_indices == NULL && max_sym_count > 0)
      || finfo.outsyms == NULL
      || (finfo.linenos == NULL && max_lineno_count > 0)
      || (finfo.contents == NULL && max_contents_size > 0)
      || (finfo.external_relocs == NULL && max_reloc_count > 0)
      || (! info->relocatable
         && finfo.internal_relocs == NULL
         && max_reloc_count > 0))
    goto error_return;

  /* We now know the position of everything in the file, except that
     we don't know the size of the symbol table and therefore we don't
     know where the string table starts.  We just build the string
     table in memory as we go along.  We process all the relocations
     for a single input file at once.  */
  obj_raw_syment_count (abfd) = 0;

  if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
    {
      if (! bfd_coff_start_final_link (abfd, info))
       goto error_return;
    }

  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_family_coff (p->u.indirect.section->owner))
           {
             sub = p->u.indirect.section->owner;
             if (! bfd_coff_link_output_has_begun (sub, & finfo))
              {
                if (! _bfd_coff_link_input_bfd (&finfo, sub))
                  goto error_return;
                sub->output_has_begun = TRUE;
              }
           }
         else if (p->type == bfd_section_reloc_link_order
                 || p->type == bfd_symbol_reloc_link_order)
           {
             if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
              goto error_return;
           }
         else
           {
             if (! _bfd_default_link_order (abfd, info, o, p))
              goto error_return;
           }
       }
    }

  if (! bfd_coff_final_link_postscript (abfd, & finfo))
    goto error_return;

  /* Free up the buffers used by _bfd_coff_link_input_bfd.  */

  coff_debug_merge_hash_table_free (&finfo.debug_merge);
  debug_merge_allocated = FALSE;

  if (finfo.internal_syms != NULL)
    {
      free (finfo.internal_syms);
      finfo.internal_syms = NULL;
    }
  if (finfo.sec_ptrs != NULL)
    {
      free (finfo.sec_ptrs);
      finfo.sec_ptrs = NULL;
    }
  if (finfo.sym_indices != NULL)
    {
      free (finfo.sym_indices);
      finfo.sym_indices = NULL;
    }
  if (finfo.linenos != NULL)
    {
      free (finfo.linenos);
      finfo.linenos = NULL;
    }
  if (finfo.contents != NULL)
    {
      free (finfo.contents);
      finfo.contents = NULL;
    }
  if (finfo.external_relocs != NULL)
    {
      free (finfo.external_relocs);
      finfo.external_relocs = NULL;
    }
  if (finfo.internal_relocs != NULL)
    {
      free (finfo.internal_relocs);
      finfo.internal_relocs = NULL;
    }

  /* The value of the last C_FILE symbol is supposed to be the symbol
     index of the first external symbol.  Write it out again if
     necessary.  */
  if (finfo.last_file_index != -1
      && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
    {
      file_ptr pos;

      finfo.last_file.n_value = obj_raw_syment_count (abfd);
      bfd_coff_swap_sym_out (abfd, &finfo.last_file,
                          finfo.outsyms);

      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0
         || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
       return FALSE;
    }

  /* If doing task linking (ld --task-link) then make a pass through the
     global symbols, writing out any that are defined, and making them
     static.  */
  if (info->task_link)
    {
      finfo.failed = FALSE;
      coff_link_hash_traverse (coff_hash_table (info),
                            _bfd_coff_write_task_globals, &finfo);
      if (finfo.failed)
       goto error_return;
    }

  /* Write out the global symbols.  */
  finfo.failed = FALSE;
  coff_link_hash_traverse (coff_hash_table (info),
                        _bfd_coff_write_global_sym, &finfo);
  if (finfo.failed)
    goto error_return;

  /* The outsyms buffer is used by _bfd_coff_write_global_sym.  */
  if (finfo.outsyms != NULL)
    {
      free (finfo.outsyms);
      finfo.outsyms = NULL;
    }

  if (info->relocatable && max_output_reloc_count > 0)
    {
      /* Now that we have written out all the global symbols, we know
        the symbol indices to use for relocs against them, and we can
        finally write out the relocs.  */
      amt = max_output_reloc_count * relsz;
      external_relocs = bfd_malloc (amt);
      if (external_relocs == NULL)
       goto error_return;

      for (o = abfd->sections; o != NULL; o = o->next)
       {
         struct internal_reloc *irel;
         struct internal_reloc *irelend;
         struct coff_link_hash_entry **rel_hash;
         bfd_byte *erel;

         if (o->reloc_count == 0)
           continue;

         irel = finfo.section_info[o->target_index].relocs;
         irelend = irel + o->reloc_count;
         rel_hash = finfo.section_info[o->target_index].rel_hashes;
         erel = external_relocs;
         for (; irel < irelend; irel++, rel_hash++, erel += relsz)
           {
             if (*rel_hash != NULL)
              {
                BFD_ASSERT ((*rel_hash)->indx >= 0);
                irel->r_symndx = (*rel_hash)->indx;
              }
             bfd_coff_swap_reloc_out (abfd, irel, erel);
           }

         if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0)
           goto error_return;
         if (obj_pe (abfd) && o->reloc_count >= 0xffff)
           {
             /* In PE COFF, write the count of relocs as the first
               reloc.  The header overflow bit will be set
               elsewhere. */
             struct internal_reloc incount;
             bfd_byte *excount = (bfd_byte *)bfd_malloc (relsz);
             
             memset (&incount, 0, sizeof (incount));
             incount.r_vaddr = o->reloc_count + 1;
             bfd_coff_swap_reloc_out (abfd, (PTR) &incount, (PTR) excount);
             if (bfd_bwrite (excount, relsz, abfd) != relsz)
              /* We'll leak, but it's an error anyway. */
              goto error_return;
             free (excount);
           }
         if (bfd_bwrite (external_relocs,
                       (bfd_size_type) relsz * o->reloc_count, abfd)
             != (bfd_size_type) relsz * o->reloc_count)
           goto error_return;
       }

      free (external_relocs);
      external_relocs = NULL;
    }

  /* Free up the section information.  */
  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
      finfo.section_info = NULL;
    }

  /* If we have optimized stabs strings, output them.  */
  if (coff_hash_table (info)->stab_info.stabstr != NULL)
    {
      if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
       return FALSE;
    }

  /* Write out the string table.  */
  if (obj_raw_syment_count (abfd) != 0 || long_section_names)
    {
      file_ptr pos;

      pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
       return FALSE;

#if STRING_SIZE_SIZE == 4
      H_PUT_32 (abfd,
              _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
              strbuf);
#else
 #error Change H_PUT_32 above
#endif

      if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd)
         != STRING_SIZE_SIZE)
       return FALSE;

      if (! _bfd_stringtab_emit (abfd, finfo.strtab))
       return FALSE;

      obj_coff_strings_written (abfd) = TRUE;
    }

  _bfd_stringtab_free (finfo.strtab);

  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
     not try to write out the symbols.  */
  bfd_get_symcount (abfd) = 0;

  return TRUE;

 error_return:
  if (debug_merge_allocated)
    coff_debug_merge_hash_table_free (&finfo.debug_merge);
  if (finfo.strtab != NULL)
    _bfd_stringtab_free (finfo.strtab);
  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
    }
  if (finfo.internal_syms != NULL)
    free (finfo.internal_syms);
  if (finfo.sec_ptrs != NULL)
    free (finfo.sec_ptrs);
  if (finfo.sym_indices != NULL)
    free (finfo.sym_indices);
  if (finfo.outsyms != NULL)
    free (finfo.outsyms);
  if (finfo.linenos != NULL)
    free (finfo.linenos);
  if (finfo.contents != NULL)
    free (finfo.contents);
  if (finfo.external_relocs != NULL)
    free (finfo.external_relocs);
  if (finfo.internal_relocs != NULL)
    free (finfo.internal_relocs);
  if (external_relocs != NULL)
    free (external_relocs);
  return FALSE;
}

Definition at line 2825 of file cofflink.c.

{
  struct internal_reloc *rel;
  struct internal_reloc *relend;

  rel = relocs;
  relend = rel + input_section->reloc_count;
  for (; rel < relend; rel++)
    {
      long symndx;
      struct coff_link_hash_entry *h;
      struct internal_syment *sym;
      bfd_vma addend;
      bfd_vma val;
      reloc_howto_type *howto;
      bfd_reloc_status_type rstat;

      symndx = rel->r_symndx;

      if (symndx == -1)
       {
         h = NULL;
         sym = NULL;
       }
      else if (symndx < 0
              || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
       {
         (*_bfd_error_handler)
           ("%B: illegal symbol index %ld in relocs", input_bfd, symndx);
         return FALSE;
       }
      else
       {
         h = obj_coff_sym_hashes (input_bfd)[symndx];
         sym = syms + symndx;
       }

      /* COFF treats common symbols in one of two ways.  Either the
         size of the symbol is included in the section contents, or it
         is not.  We assume that the size is not included, and force
         the rtype_to_howto function to adjust the addend as needed.  */
      if (sym != NULL && sym->n_scnum != 0)
       addend = - sym->n_value;
      else
       addend = 0;

      howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
                                   sym, &addend);
      if (howto == NULL)
       return FALSE;

      /* If we are doing a relocatable link, then we can just ignore
         a PC relative reloc that is pcrel_offset.  It will already
         have the correct value.  If this is not a relocatable link,
         then we should ignore the symbol value.  */
      if (howto->pc_relative && howto->pcrel_offset)
       {
         if (info->relocatable)
           continue;
         if (sym != NULL && sym->n_scnum != 0)
           addend += sym->n_value;
       }

      val = 0;

      if (h == NULL)
       {
         asection *sec;

         if (symndx == -1)
           {
             sec = bfd_abs_section_ptr;
             val = 0;
           }
         else
           {
             sec = sections[symndx];
              val = (sec->output_section->vma
                   + sec->output_offset
                   + sym->n_value);
             if (! obj_pe (input_bfd))
              val -= sec->vma;
           }
       }
      else
       {
         if (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak)
           {
             /* Defined weak symbols are a GNU extension. */
             asection *sec;

             sec = h->root.u.def.section;
             val = (h->root.u.def.value
                   + sec->output_section->vma
                   + sec->output_offset);
           }

         else if (h->root.type == bfd_link_hash_undefweak)
           {
              if (h->class == C_NT_WEAK && h->numaux == 1)
              {
                /* See _Microsoft Portable Executable and Common Object
                     File Format Specification_, section 5.5.3.
                   Note that weak symbols without aux records are a GNU
                   extension.
                   FIXME: All weak externals are treated as having
                   characteristic IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY (1).
                   These behave as per SVR4 ABI:  A library member
                   will resolve a weak external only if a normal
                   external causes the library member to be linked.
                   See also linker.c: generic_link_check_archive_element. */
                asection *sec;
                struct coff_link_hash_entry *h2 =
                  input_bfd->tdata.coff_obj_data->sym_hashes[
                  h->aux->x_sym.x_tagndx.l];

                if (!h2 || h2->root.type == bfd_link_hash_undefined)
                  {
                    sec = bfd_abs_section_ptr;
                    val = 0;
                  }
                else
                  {
                    sec = h2->root.u.def.section;
                    val = h2->root.u.def.value
                     + sec->output_section->vma + sec->output_offset;
                  }
              }
             else
                /* This is a GNU extension.  */
              val = 0;
           }

         else if (! info->relocatable)
           {
             if (! ((*info->callbacks->undefined_symbol)
                   (info, h->root.root.string, input_bfd, input_section,
                    rel->r_vaddr - input_section->vma, TRUE)))
              return FALSE;
           }
       }

      if (info->base_file)
       {
         /* Emit a reloc if the backend thinks it needs it.  */
         if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
           {
             /* Relocation to a symbol in a section which isn't
               absolute.  We output the address here to a file.
               This file is then read by dlltool when generating the
               reloc section.  Note that the base file is not
               portable between systems.  We write out a long here,
               and dlltool reads in a long.  */
             long addr = (rel->r_vaddr
                        - input_section->vma
                        + input_section->output_offset
                        + input_section->output_section->vma);
             if (coff_data (output_bfd)->pe)
              addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
             if (fwrite (&addr, 1, sizeof (long), (FILE *) info->base_file)
                != sizeof (long))
              {
                bfd_set_error (bfd_error_system_call);
                return FALSE;
              }
           }
       }

      rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents,
                                   rel->r_vaddr - input_section->vma,
                                   val, addend);

      switch (rstat)
       {
       default:
         abort ();
       case bfd_reloc_ok:
         break;
       case bfd_reloc_outofrange:
         (*_bfd_error_handler)
           (_("%B: bad reloc address 0x%lx in section `%A'"),
            input_bfd, input_section, (unsigned long) rel->r_vaddr);
         return FALSE;
       case bfd_reloc_overflow:
         {
           const char *name;
           char buf[SYMNMLEN + 1];

           if (symndx == -1)
             name = "*ABS*";
           else if (h != NULL)
             name = NULL;
           else
             {
              name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
              if (name == NULL)
                return FALSE;
             }

           if (! ((*info->callbacks->reloc_overflow)
                 (info, (h ? &h->root : NULL), name, howto->name,
                  (bfd_vma) 0, input_bfd, input_section,
                  rel->r_vaddr - input_section->vma)))
             return FALSE;
         }
       }
    }
  return TRUE;
}

Definition at line 1434 of file coffgen.c.

{
  bfd_size_type symesz;
  bfd_size_type size;
  void * syms;

  if (obj_coff_external_syms (abfd) != NULL)
    return TRUE;

  symesz = bfd_coff_symesz (abfd);

  size = obj_raw_syment_count (abfd) * symesz;

  syms = bfd_malloc (size);
  if (syms == NULL && size != 0)
    return FALSE;

  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
      || bfd_bread (syms, size, abfd) != size)
    {
      if (syms != NULL)
       free (syms);
      return FALSE;
    }

  obj_coff_external_syms (abfd) = syms;

  return TRUE;
}

Definition at line 357 of file coffgen.c.

{
  /* FIXME: It's not clear this will work correctly if sizeof
     (_n_zeroes) != 4.  */
  if (sym->_n._n_n._n_zeroes != 0
      || sym->_n._n_n._n_offset == 0)
    {
      memcpy (buf, sym->_n._n_name, SYMNMLEN);
      buf[SYMNMLEN] = '\0';
      return buf;
    }
  else
    {
      const char *strings;

      BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE);
      strings = obj_coff_strings (abfd);
      if (strings == NULL)
       {
         strings = _bfd_coff_read_string_table (abfd);
         if (strings == NULL)
           return NULL;
       }
      return strings + sym->_n._n_n._n_offset;
    }
}

Definition at line 58 of file cofflink.c.

{
  struct coff_link_hash_entry *ret = (struct coff_link_hash_entry *) entry;

  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
  if (ret == (struct coff_link_hash_entry *) NULL)
    ret = ((struct coff_link_hash_entry *)
          bfd_hash_allocate (table, sizeof (struct coff_link_hash_entry)));
  if (ret == (struct coff_link_hash_entry *) NULL)
    return (struct bfd_hash_entry *) ret;

  /* Call the allocation method of the superclass.  */
  ret = ((struct coff_link_hash_entry *)
        _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                             table, string));
  if (ret != (struct coff_link_hash_entry *) NULL)
    {
      /* Set local fields.  */
      ret->indx = -1;
      ret->type = T_NULL;
      ret->class = C_NULL;
      ret->numaux = 0;
      ret->auxbfd = NULL;
      ret->aux = NULL;
    }

  return (struct bfd_hash_entry *) ret;
}

Definition at line 107 of file cofflink.c.

{
  struct coff_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct coff_link_hash_table);

  ret = bfd_malloc (amt);
  if (ret == NULL)
    return NULL;

  if (! _bfd_coff_link_hash_table_init (ret, abfd,
                                   _bfd_coff_link_hash_newfunc,
                                   sizeof (struct coff_link_hash_entry)))
    {
      free (ret);
      return (struct bfd_link_hash_table *) NULL;
    }
  return &ret->root;
}
bfd_boolean _bfd_coff_link_hash_table_init ( struct coff_link_hash_table ,
bfd ,
struct bfd_hash_entry *)(struct bfd_hash_entry *, struct bfd_hash_table *, const char *,
unsigned  int 
)

Definition at line 1342 of file cofflink.c.

{
  unsigned int n_tmask = coff_data (input_bfd)->local_n_tmask;
  unsigned int n_btshft = coff_data (input_bfd)->local_n_btshft;
  bfd_boolean (*adjust_symndx)
    (bfd *, struct bfd_link_info *, bfd *, asection *,
     struct internal_reloc *, bfd_boolean *);
  bfd *output_bfd;
  const char *strings;
  bfd_size_type syment_base;
  bfd_boolean copy, hash;
  bfd_size_type isymesz;
  bfd_size_type osymesz;
  bfd_size_type linesz;
  bfd_byte *esym;
  bfd_byte *esym_end;
  struct internal_syment *isymp;
  asection **secpp;
  long *indexp;
  unsigned long output_index;
  bfd_byte *outsym;
  struct coff_link_hash_entry **sym_hash;
  asection *o;

  /* Move all the symbols to the output file.  */

  output_bfd = finfo->output_bfd;
  strings = NULL;
  syment_base = obj_raw_syment_count (output_bfd);
  isymesz = bfd_coff_symesz (input_bfd);
  osymesz = bfd_coff_symesz (output_bfd);
  linesz = bfd_coff_linesz (input_bfd);
  BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));

  copy = FALSE;
  if (! finfo->info->keep_memory)
    copy = TRUE;
  hash = TRUE;
  if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
    hash = FALSE;

  if (! _bfd_coff_get_external_symbols (input_bfd))
    return FALSE;

  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
  isymp = finfo->internal_syms;
  secpp = finfo->sec_ptrs;
  indexp = finfo->sym_indices;
  output_index = syment_base;
  outsym = finfo->outsyms;

  if (coff_data (output_bfd)->pe
      && ! process_embedded_commands (output_bfd, finfo->info, input_bfd))
    return FALSE;

  /* If we are going to perform relocations and also strip/discard some
     symbols then we must make sure that we do not strip/discard those
     symbols that are going to be involved in the relocations.  */
  if ((   finfo->info->strip   != strip_none
       || finfo->info->discard != discard_none)
      && finfo->info->relocatable)
    {
      /* Mark the symbol array as 'not-used'.  */
      memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);

      mark_relocs (finfo, input_bfd);
    }

  while (esym < esym_end)
    {
      struct internal_syment isym;
      enum coff_symbol_classification classification;
      bfd_boolean skip;
      bfd_boolean global;
      bfd_boolean dont_skip_symbol;
      int add;

      bfd_coff_swap_sym_in (input_bfd, esym, isymp);

      /* Make a copy of *isymp so that the relocate_section function
        always sees the original values.  This is more reliable than
        always recomputing the symbol value even if we are stripping
        the symbol.  */
      isym = *isymp;

      classification = bfd_coff_classify_symbol (input_bfd, &isym);
      switch (classification)
       {
       default:
         abort ();
       case COFF_SYMBOL_GLOBAL:
       case COFF_SYMBOL_PE_SECTION:
       case COFF_SYMBOL_LOCAL:
         *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
         break;
       case COFF_SYMBOL_COMMON:
         *secpp = bfd_com_section_ptr;
         break;
       case COFF_SYMBOL_UNDEFINED:
         *secpp = bfd_und_section_ptr;
         break;
       }

      /* Extract the flag indicating if this symbol is used by a
         relocation.  */
      if ((finfo->info->strip != strip_none
          || finfo->info->discard != discard_none)
         && finfo->info->relocatable)
       dont_skip_symbol = *indexp;
      else
       dont_skip_symbol = FALSE;

      *indexp = -1;

      skip = FALSE;
      global = FALSE;
      add = 1 + isym.n_numaux;

      /* If we are stripping all symbols, we want to skip this one.  */
      if (finfo->info->strip == strip_all && ! dont_skip_symbol)
       skip = TRUE;

      if (! skip)
       {
         switch (classification)
           {
           default:
             abort ();
           case COFF_SYMBOL_GLOBAL:
           case COFF_SYMBOL_COMMON:
           case COFF_SYMBOL_PE_SECTION:
             /* This is a global symbol.  Global symbols come at the
               end of the symbol table, so skip them for now.
               Locally defined function symbols, however, are an
               exception, and are not moved to the end.  */
             global = TRUE;
             if (! ISFCN (isym.n_type))
              skip = TRUE;
             break;

           case COFF_SYMBOL_UNDEFINED:
             /* Undefined symbols are left for the end.  */
             global = TRUE;
             skip = TRUE;
             break;

           case COFF_SYMBOL_LOCAL:
             /* This is a local symbol.  Skip it if we are discarding
                 local symbols.  */
             if (finfo->info->discard == discard_all && ! dont_skip_symbol)
              skip = TRUE;
             break;
           }
       }

#ifndef COFF_WITH_PE
      /* Skip section symbols for sections which are not going to be
        emitted.  */
      if (!skip
         && dont_skip_symbol == 0
         && isym.n_sclass == C_STAT
         && isym.n_type == T_NULL
          && isym.n_numaux > 0
         && (*secpp)->output_section == bfd_abs_section_ptr)
       skip = TRUE;
#endif

      /* If we stripping debugging symbols, and this is a debugging
         symbol, then skip it.  FIXME: gas sets the section to N_ABS
         for some types of debugging symbols; I don't know if this is
         a bug or not.  In any case, we handle it here.  */
      if (! skip
         && finfo->info->strip == strip_debugger
         && ! dont_skip_symbol
         && (isym.n_scnum == N_DEBUG
             || (isym.n_scnum == N_ABS
                && (isym.n_sclass == C_AUTO
                    || isym.n_sclass == C_REG
                    || isym.n_sclass == C_MOS
                    || isym.n_sclass == C_MOE
                    || isym.n_sclass == C_MOU
                    || isym.n_sclass == C_ARG
                    || isym.n_sclass == C_REGPARM
                    || isym.n_sclass == C_FIELD
                    || isym.n_sclass == C_EOS))))
       skip = TRUE;

      /* If some symbols are stripped based on the name, work out the
        name and decide whether to skip this symbol.  */
      if (! skip
         && (finfo->info->strip == strip_some
             || finfo->info->discard == discard_l))
       {
         const char *name;
         char buf[SYMNMLEN + 1];

         name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
         if (name == NULL)
           return FALSE;

         if (! dont_skip_symbol
             && ((finfo->info->strip == strip_some
                 && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE,
                                FALSE) == NULL))
                 || (! global
                     && finfo->info->discard == discard_l
                     && bfd_is_local_label_name (input_bfd, name))))
           skip = TRUE;
       }

      /* If this is an enum, struct, or union tag, see if we have
         already output an identical type.  */
      if (! skip
         && (finfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0
         && (isym.n_sclass == C_ENTAG
             || isym.n_sclass == C_STRTAG
             || isym.n_sclass == C_UNTAG)
         && isym.n_numaux == 1)
       {
         const char *name;
         char buf[SYMNMLEN + 1];
         struct coff_debug_merge_hash_entry *mh;
         struct coff_debug_merge_type *mt;
         union internal_auxent aux;
         struct coff_debug_merge_element **epp;
         bfd_byte *esl, *eslend;
         struct internal_syment *islp;
         bfd_size_type amt;

         name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
         if (name == NULL)
           return FALSE;

         /* Ignore fake names invented by compiler; treat them all as
             the same name.  */
         if (*name == '~' || *name == '.' || *name == '$'
             || (*name == bfd_get_symbol_leading_char (input_bfd)
                && (name[1] == '~' || name[1] == '.' || name[1] == '$')))
           name = "";

         mh = coff_debug_merge_hash_lookup (&finfo->debug_merge, name,
                                        TRUE, TRUE);
         if (mh == NULL)
           return FALSE;

         /* Allocate memory to hold type information.  If this turns
             out to be a duplicate, we pass this address to
             bfd_release.  */
         amt = sizeof (struct coff_debug_merge_type);
         mt = bfd_alloc (input_bfd, amt);
         if (mt == NULL)
           return FALSE;
         mt->class = isym.n_sclass;

         /* Pick up the aux entry, which points to the end of the tag
             entries.  */
         bfd_coff_swap_aux_in (input_bfd, (esym + isymesz),
                            isym.n_type, isym.n_sclass, 0, isym.n_numaux,
                            &aux);

         /* Gather the elements.  */
         epp = &mt->elements;
         mt->elements = NULL;
         islp = isymp + 2;
         esl = esym + 2 * isymesz;
         eslend = ((bfd_byte *) obj_coff_external_syms (input_bfd)
                  + aux.x_sym.x_fcnary.x_fcn.x_endndx.l * isymesz);
         while (esl < eslend)
           {
             const char *elename;
             char elebuf[SYMNMLEN + 1];
             char *name_copy;

             bfd_coff_swap_sym_in (input_bfd, esl, islp);

             amt = sizeof (struct coff_debug_merge_element);
             *epp = bfd_alloc (input_bfd, amt);
             if (*epp == NULL)
              return FALSE;

             elename = _bfd_coff_internal_syment_name (input_bfd, islp,
                                                 elebuf);
             if (elename == NULL)
              return FALSE;

             amt = strlen (elename) + 1;
             name_copy = bfd_alloc (input_bfd, amt);
             if (name_copy == NULL)
              return FALSE;
             strcpy (name_copy, elename);

             (*epp)->name = name_copy;
             (*epp)->type = islp->n_type;
             (*epp)->tagndx = 0;
             if (islp->n_numaux >= 1
                && islp->n_type != T_NULL
                && islp->n_sclass != C_EOS)
              {
                union internal_auxent eleaux;
                long indx;

                bfd_coff_swap_aux_in (input_bfd, (esl + isymesz),
                                   islp->n_type, islp->n_sclass, 0,
                                   islp->n_numaux, &eleaux);
                indx = eleaux.x_sym.x_tagndx.l;

                /* FIXME: If this tagndx entry refers to a symbol
                   defined later in this file, we just ignore it.
                   Handling this correctly would be tedious, and may
                   not be required.  */
                if (indx > 0
                    && (indx
                       < ((esym -
                           (bfd_byte *) obj_coff_external_syms (input_bfd))
                          / (long) isymesz)))
                  {
                    (*epp)->tagndx = finfo->sym_indices[indx];
                    if ((*epp)->tagndx < 0)
                     (*epp)->tagndx = 0;
                  }
              }
             epp = &(*epp)->next;
             *epp = NULL;

             esl += (islp->n_numaux + 1) * isymesz;
             islp += islp->n_numaux + 1;
           }

         /* See if we already have a definition which matches this
             type.  We always output the type if it has no elements,
             for simplicity.  */
         if (mt->elements == NULL)
           bfd_release (input_bfd, mt);
         else
           {
             struct coff_debug_merge_type *mtl;

             for (mtl = mh->types; mtl != NULL; mtl = mtl->next)
              {
                struct coff_debug_merge_element *me, *mel;

                if (mtl->class != mt->class)
                  continue;

                for (me = mt->elements, mel = mtl->elements;
                     me != NULL && mel != NULL;
                     me = me->next, mel = mel->next)
                  {
                    if (strcmp (me->name, mel->name) != 0
                       || me->type != mel->type
                       || me->tagndx != mel->tagndx)
                     break;
                  }

                if (me == NULL && mel == NULL)
                  break;
              }

             if (mtl == NULL || (bfd_size_type) mtl->indx >= syment_base)
              {
                /* This is the first definition of this type.  */
                mt->indx = output_index;
                mt->next = mh->types;
                mh->types = mt;
              }
             else
              {
                /* This is a redefinition which can be merged.  */
                bfd_release (input_bfd, mt);
                *indexp = mtl->indx;
                add = (eslend - esym) / isymesz;
                skip = TRUE;
              }
           }
       }

      /* We now know whether we are to skip this symbol or not.  */
      if (! skip)
       {
         /* Adjust the symbol in order to output it.  */

         if (isym._n._n_n._n_zeroes == 0
             && isym._n._n_n._n_offset != 0)
           {
             const char *name;
             bfd_size_type indx;

             /* This symbol has a long name.  Enter it in the string
               table we are building.  Note that we do not check
               bfd_coff_symname_in_debug.  That is only true for
               XCOFF, and XCOFF requires different linking code
               anyhow.  */
             name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
             if (name == NULL)
              return FALSE;
             indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
             if (indx == (bfd_size_type) -1)
              return FALSE;
             isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
           }

         switch (isym.n_sclass)
           {
           case C_AUTO:
           case C_MOS:
           case C_EOS:
           case C_MOE:
           case C_MOU:
           case C_UNTAG:
           case C_STRTAG:
           case C_ENTAG:
           case C_TPDEF:
           case C_ARG:
           case C_USTATIC:
           case C_REG:
           case C_REGPARM:
           case C_FIELD:
             /* The symbol value should not be modified.  */
             break;

           case C_FCN:
             if (obj_pe (input_bfd)
                && strcmp (isym.n_name, ".bf") != 0
                && isym.n_scnum > 0)
              {
                /* For PE, .lf and .ef get their value left alone,
                   while .bf gets relocated.  However, they all have
                   "real" section numbers, and need to be moved into
                   the new section.  */
                isym.n_scnum = (*secpp)->output_section->target_index;
                break;
              }
             /* Fall through.  */
           default:
           case C_LABEL:  /* Not completely sure about these 2 */
           case C_EXTDEF:
           case C_BLOCK:
           case C_EFCN:
           case C_NULL:
           case C_EXT:
           case C_STAT:
           case C_SECTION:
           case C_NT_WEAK:
             /* Compute new symbol location.  */
           if (isym.n_scnum > 0)
             {
              isym.n_scnum = (*secpp)->output_section->target_index;
              isym.n_value += (*secpp)->output_offset;
              if (! obj_pe (input_bfd))
                isym.n_value -= (*secpp)->vma;
              if (! obj_pe (finfo->output_bfd))
                isym.n_value += (*secpp)->output_section->vma;
             }
           break;

           case C_FILE:
             /* The value of a C_FILE symbol is the symbol index of
               the next C_FILE symbol.  The value of the last C_FILE
               symbol is the symbol index to the first external
               symbol (actually, coff_renumber_symbols does not get
               this right--it just sets the value of the last C_FILE
               symbol to zero--and nobody has ever complained about
               it).  We try to get this right, below, just before we
               write the symbols out, but in the general case we may
               have to write the symbol out twice.  */
             if (finfo->last_file_index != -1
                && finfo->last_file.n_value != (bfd_vma) output_index)
              {
                /* We must correct the value of the last C_FILE
                     entry.  */
                finfo->last_file.n_value = output_index;
                if ((bfd_size_type) finfo->last_file_index >= syment_base)
                  {
                    /* The last C_FILE symbol is in this input file.  */
                    bfd_coff_swap_sym_out (output_bfd,
                                        &finfo->last_file,
                                        (finfo->outsyms
                                         + ((finfo->last_file_index
                                            - syment_base)
                                           * osymesz)));
                  }
                else
                  {
                    file_ptr pos;

                    /* We have already written out the last C_FILE
                      symbol.  We need to write it out again.  We
                      borrow *outsym temporarily.  */
                    bfd_coff_swap_sym_out (output_bfd,
                                        &finfo->last_file, outsym);
                    pos = obj_sym_filepos (output_bfd);
                    pos += finfo->last_file_index * osymesz;
                    if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                       || bfd_bwrite (outsym, osymesz, output_bfd) != osymesz)
                     return FALSE;
                  }
              }

             finfo->last_file_index = output_index;
             finfo->last_file = isym;
             break;
           }

         /* If doing task linking, convert normal global function symbols to
            static functions.  */
         if (finfo->info->task_link && IS_EXTERNAL (input_bfd, isym))
           isym.n_sclass = C_STAT;

         /* Output the symbol.  */
         bfd_coff_swap_sym_out (output_bfd, &isym, outsym);

         *indexp = output_index;

         if (global)
           {
             long indx;
             struct coff_link_hash_entry *h;

             indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
                    / isymesz);
             h = obj_coff_sym_hashes (input_bfd)[indx];
             if (h == NULL)
              {
                /* This can happen if there were errors earlier in
                     the link.  */
                bfd_set_error (bfd_error_bad_value);
                return FALSE;
              }
             h->indx = output_index;
           }

         output_index += add;
         outsym += add * osymesz;
       }

      esym += add * isymesz;
      isymp += add;
      ++secpp;
      ++indexp;
      for (--add; add > 0; --add)
       {
         *secpp++ = NULL;
         *indexp++ = -1;
       }
    }

  /* Fix up the aux entries.  This must be done in a separate pass,
     because we don't know the correct symbol indices until we have
     already decided which symbols we are going to keep.  */
  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
  isymp = finfo->internal_syms;
  indexp = finfo->sym_indices;
  sym_hash = obj_coff_sym_hashes (input_bfd);
  outsym = finfo->outsyms;

  while (esym < esym_end)
    {
      int add;

      add = 1 + isymp->n_numaux;

      if ((*indexp < 0
          || (bfd_size_type) *indexp < syment_base)
         && (*sym_hash == NULL
             || (*sym_hash)->auxbfd != input_bfd))
       esym += add * isymesz;
      else
       {
         struct coff_link_hash_entry *h;
         int i;

         h = NULL;
         if (*indexp < 0)
           {
             h = *sym_hash;

             /* The m68k-motorola-sysv assembler will sometimes
                 generate two symbols with the same name, but only one
                 will have aux entries.  */
             BFD_ASSERT (isymp->n_numaux == 0
                       || h->numaux == 0
                       || h->numaux == isymp->n_numaux);
           }

         esym += isymesz;

         if (h == NULL)
           outsym += osymesz;

         /* Handle the aux entries.  This handling is based on
            coff_pointerize_aux.  I don't know if it always correct.  */
         for (i = 0; i < isymp->n_numaux && esym < esym_end; i++)
           {
             union internal_auxent aux;
             union internal_auxent *auxp;

             if (h != NULL && h->aux != NULL && (h->numaux > i))
              auxp = h->aux + i;
             else
              {
                bfd_coff_swap_aux_in (input_bfd, esym, isymp->n_type,
                                   isymp->n_sclass, i, isymp->n_numaux, &aux);
                auxp = &aux;
              }

             if (isymp->n_sclass == C_FILE)
              {
                /* If this is a long filename, we must put it in the
                   string table.  */
                if (auxp->x_file.x_n.x_zeroes == 0
                    && auxp->x_file.x_n.x_offset != 0)
                  {
                    const char *filename;
                    bfd_size_type indx;

                    BFD_ASSERT (auxp->x_file.x_n.x_offset
                              >= STRING_SIZE_SIZE);
                    if (strings == NULL)
                     {
                       strings = _bfd_coff_read_string_table (input_bfd);
                       if (strings == NULL)
                         return FALSE;
                     }
                    filename = strings + auxp->x_file.x_n.x_offset;
                    indx = _bfd_stringtab_add (finfo->strtab, filename,
                                           hash, copy);
                    if (indx == (bfd_size_type) -1)
                     return FALSE;
                    auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
                  }
              }
             else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
                     && isymp->n_sclass != C_NT_WEAK)
              {
                unsigned long indx;

                if (ISFCN (isymp->n_type)
                    || ISTAG (isymp->n_sclass)
                    || isymp->n_sclass == C_BLOCK
                    || isymp->n_sclass == C_FCN)
                  {
                    indx = auxp->x_sym.x_fcnary.x_fcn.x_endndx.l;
                    if (indx > 0
                       && indx < obj_raw_syment_count (input_bfd))
                     {
                       /* We look forward through the symbol for
                             the index of the next symbol we are going
                             to include.  I don't know if this is
                             entirely right.  */
                       while ((finfo->sym_indices[indx] < 0
                              || ((bfd_size_type) finfo->sym_indices[indx]
                                  < syment_base))
                             && indx < obj_raw_syment_count (input_bfd))
                         ++indx;
                       if (indx >= obj_raw_syment_count (input_bfd))
                         indx = output_index;
                       else
                         indx = finfo->sym_indices[indx];
                       auxp->x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
                     }
                  }

                indx = auxp->x_sym.x_tagndx.l;
                if (indx > 0 && indx < obj_raw_syment_count (input_bfd))
                  {
                    long symindx;

                    symindx = finfo->sym_indices[indx];
                    if (symindx < 0)
                     auxp->x_sym.x_tagndx.l = 0;
                    else
                     auxp->x_sym.x_tagndx.l = symindx;
                  }

                /* The .bf symbols are supposed to be linked through
                   the endndx field.  We need to carry this list
                   across object files.  */
                if (i == 0
                    && h == NULL
                    && isymp->n_sclass == C_FCN
                    && (isymp->_n._n_n._n_zeroes != 0
                       || isymp->_n._n_n._n_offset == 0)
                    && isymp->_n._n_name[0] == '.'
                    && isymp->_n._n_name[1] == 'b'
                    && isymp->_n._n_name[2] == 'f'
                    && isymp->_n._n_name[3] == '\0')
                  {
                    if (finfo->last_bf_index != -1)
                     {
                       finfo->last_bf.x_sym.x_fcnary.x_fcn.x_endndx.l =
                         *indexp;

                       if ((bfd_size_type) finfo->last_bf_index
                           >= syment_base)
                         {
                           void *auxout;

                           /* The last .bf symbol is in this input
                             file.  This will only happen if the
                             assembler did not set up the .bf
                             endndx symbols correctly.  */
                           auxout = (finfo->outsyms
                                   + ((finfo->last_bf_index
                                       - syment_base)
                                      * osymesz));

                           bfd_coff_swap_aux_out (output_bfd,
                                               &finfo->last_bf,
                                               isymp->n_type,
                                               isymp->n_sclass,
                                               0, isymp->n_numaux,
                                               auxout);
                         }
                       else
                         {
                           file_ptr pos;

                           /* We have already written out the last
                                 .bf aux entry.  We need to write it
                                 out again.  We borrow *outsym
                                 temporarily.  FIXME: This case should
                                 be made faster.  */
                           bfd_coff_swap_aux_out (output_bfd,
                                               &finfo->last_bf,
                                               isymp->n_type,
                                               isymp->n_sclass,
                                               0, isymp->n_numaux,
                                               outsym);
                           pos = obj_sym_filepos (output_bfd);
                           pos += finfo->last_bf_index * osymesz;
                           if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                              || (bfd_bwrite (outsym, osymesz, output_bfd)
                                  != osymesz))
                            return FALSE;
                         }
                     }

                    if (auxp->x_sym.x_fcnary.x_fcn.x_endndx.l != 0)
                     finfo->last_bf_index = -1;
                    else
                     {
                       /* The endndx field of this aux entry must
                             be updated with the symbol number of the
                             next .bf symbol.  */
                       finfo->last_bf = *auxp;
                       finfo->last_bf_index = (((outsym - finfo->outsyms)
                                             / osymesz)
                                            + syment_base);
                     }
                  }
              }

             if (h == NULL)
              {
                bfd_coff_swap_aux_out (output_bfd, auxp, isymp->n_type,
                                    isymp->n_sclass, i, isymp->n_numaux,
                                    outsym);
                outsym += osymesz;
              }

             esym += isymesz;
           }
       }

      indexp += add;
      isymp += add;
      sym_hash += add;
    }

  /* Relocate the line numbers, unless we are stripping them.  */
  if (finfo->info->strip == strip_none
      || finfo->info->strip == strip_some)
    {
      for (o = input_bfd->sections; o != NULL; o = o->next)
       {
         bfd_vma offset;
         bfd_byte *eline;
         bfd_byte *elineend;
         bfd_byte *oeline;
         bfd_boolean skipping;
         file_ptr pos;
         bfd_size_type amt;

         /* FIXME: If SEC_HAS_CONTENTS is not for the section, then
            build_link_order in ldwrite.c will not have created a
            link order, which means that we will not have seen this
            input section in _bfd_coff_final_link, which means that
            we will not have allocated space for the line numbers of
            this section.  I don't think line numbers can be
            meaningful for a section which does not have
            SEC_HAS_CONTENTS set, but, if they do, this must be
            changed.  */
         if (o->lineno_count == 0
             || (o->output_section->flags & SEC_HAS_CONTENTS) == 0)
           continue;

         if (bfd_seek (input_bfd, o->line_filepos, SEEK_SET) != 0
             || bfd_bread (finfo->linenos, linesz * o->lineno_count,
                        input_bfd) != linesz * o->lineno_count)
           return FALSE;

         offset = o->output_section->vma + o->output_offset - o->vma;
         eline = finfo->linenos;
         oeline = finfo->linenos;
         elineend = eline + linesz * o->lineno_count;
         skipping = FALSE;
         for (; eline < elineend; eline += linesz)
           {
             struct internal_lineno iline;

             bfd_coff_swap_lineno_in (input_bfd, eline, &iline);

             if (iline.l_lnno != 0)
              iline.l_addr.l_paddr += offset;
             else if (iline.l_addr.l_symndx >= 0
                     && ((unsigned long) iline.l_addr.l_symndx
                        < obj_raw_syment_count (input_bfd)))
              {
                long indx;

                indx = finfo->sym_indices[iline.l_addr.l_symndx];

                if (indx < 0)
                  {
                    /* These line numbers are attached to a symbol
                      which we are stripping.  We must discard the
                      line numbers because reading them back with
                      no associated symbol (or associating them all
                      with symbol #0) will fail.  We can't regain
                      the space in the output file, but at least
                      they're dense.  */
                    skipping = TRUE;
                  }
                else
                  {
                    struct internal_syment is;
                    union internal_auxent ia;

                    /* Fix up the lnnoptr field in the aux entry of
                      the symbol.  It turns out that we can't do
                      this when we modify the symbol aux entries,
                      because gas sometimes screws up the lnnoptr
                      field and makes it an offset from the start
                      of the line numbers rather than an absolute
                      file index.  */
                    bfd_coff_swap_sym_in (output_bfd,
                                       (finfo->outsyms
                                        + ((indx - syment_base)
                                          * osymesz)), &is);
                    if ((ISFCN (is.n_type)
                        || is.n_sclass == C_BLOCK)
                       && is.n_numaux >= 1)
                     {
                       void *auxptr;

                       auxptr = (finfo->outsyms
                                + ((indx - syment_base + 1)
                                   * osymesz));
                       bfd_coff_swap_aux_in (output_bfd, auxptr,
                                          is.n_type, is.n_sclass,
                                          0, is.n_numaux, &ia);
                       ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                         (o->output_section->line_filepos
                          + o->output_section->lineno_count * linesz
                          + eline - finfo->linenos);
                       bfd_coff_swap_aux_out (output_bfd, &ia,
                                           is.n_type, is.n_sclass, 0,
                                           is.n_numaux, auxptr);
                     }

                    skipping = FALSE;
                  }

                iline.l_addr.l_symndx = indx;
              }

             if (!skipping)
               {
                bfd_coff_swap_lineno_out (output_bfd, &iline, oeline);
                oeline += linesz;
              }
           }

         pos = o->output_section->line_filepos;
         pos += o->output_section->lineno_count * linesz;
         amt = oeline - finfo->linenos;
         if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
             || bfd_bwrite (finfo->linenos, amt, output_bfd) != amt)
           return FALSE;

         o->output_section->lineno_count += amt / linesz;
       }
    }

  /* If we swapped out a C_FILE symbol, guess that the next C_FILE
     symbol will be the first symbol in the next input file.  In the
     normal case, this will save us from writing out the C_FILE symbol
     again.  */
  if (finfo->last_file_index != -1
      && (bfd_size_type) finfo->last_file_index >= syment_base)
    {
      finfo->last_file.n_value = output_index;
      bfd_coff_swap_sym_out (output_bfd, &finfo->last_file,
                          (finfo->outsyms
                           + ((finfo->last_file_index - syment_base)
                             * osymesz)));
    }

  /* Write the modified symbols to the output file.  */
  if (outsym > finfo->outsyms)
    {
      file_ptr pos;
      bfd_size_type amt;

      pos = obj_sym_filepos (output_bfd) + syment_base * osymesz;
      amt = outsym - finfo->outsyms;
      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
         || bfd_bwrite (finfo->outsyms, amt, output_bfd) != amt)
       return FALSE;

      BFD_ASSERT ((obj_raw_syment_count (output_bfd)
                 + (outsym - finfo->outsyms) / osymesz)
                == output_index);

      obj_raw_syment_count (output_bfd) = output_index;
    }

  /* Relocate the contents of each section.  */
  adjust_symndx = coff_backend_info (input_bfd)->_bfd_coff_adjust_symndx;
  for (o = input_bfd->sections; o != NULL; o = o->next)
    {
      bfd_byte *contents;
      struct coff_section_tdata *secdata;

      if (! o->linker_mark)
       /* This section was omitted from the link.  */
       continue;

      if ((o->flags & SEC_LINKER_CREATED) != 0)
       continue;

      if ((o->flags & SEC_HAS_CONTENTS) == 0
         || (o->size == 0 && (o->flags & SEC_RELOC) == 0))
       {
         if ((o->flags & SEC_RELOC) != 0
             && o->reloc_count != 0)
           {
             (*_bfd_error_handler)
              (_("%B: relocs in section `%A', but it has no contents"),
               input_bfd, o);
             bfd_set_error (bfd_error_no_contents);
             return FALSE;
           }

         continue;
       }

      secdata = coff_section_data (input_bfd, o);
      if (secdata != NULL && secdata->contents != NULL)
       contents = secdata->contents;
      else
       {
         bfd_size_type x = o->rawsize ? o->rawsize : o->size;
         if (! bfd_get_section_contents (input_bfd, o, finfo->contents, 0, x))
           return FALSE;
         contents = finfo->contents;
       }

      if ((o->flags & SEC_RELOC) != 0)
       {
         int target_index;
         struct internal_reloc *internal_relocs;
         struct internal_reloc *irel;

         /* Read in the relocs.  */
         target_index = o->output_section->target_index;
         internal_relocs = (_bfd_coff_read_internal_relocs
                          (input_bfd, o, FALSE, finfo->external_relocs,
                           finfo->info->relocatable,
                           (finfo->info->relocatable
                            ? (finfo->section_info[target_index].relocs
                              + o->output_section->reloc_count)
                            : finfo->internal_relocs)));
         if (internal_relocs == NULL)
           return FALSE;

         /* Call processor specific code to relocate the section
             contents.  */
         if (! bfd_coff_relocate_section (output_bfd, finfo->info,
                                      input_bfd, o,
                                      contents,
                                      internal_relocs,
                                      finfo->internal_syms,
                                      finfo->sec_ptrs))
           return FALSE;

         if (finfo->info->relocatable)
           {
             bfd_vma offset;
             struct internal_reloc *irelend;
             struct coff_link_hash_entry **rel_hash;

             offset = o->output_section->vma + o->output_offset - o->vma;
             irel = internal_relocs;
             irelend = irel + o->reloc_count;
             rel_hash = (finfo->section_info[target_index].rel_hashes
                       + o->output_section->reloc_count);
             for (; irel < irelend; irel++, rel_hash++)
              {
                struct coff_link_hash_entry *h;
                bfd_boolean adjusted;

                *rel_hash = NULL;

                /* Adjust the reloc address and symbol index.  */
                irel->r_vaddr += offset;

                if (irel->r_symndx == -1)
                  continue;

                if (adjust_symndx)
                  {
                    if (! (*adjust_symndx) (output_bfd, finfo->info,
                                         input_bfd, o, irel,
                                         &adjusted))
                     return FALSE;
                    if (adjusted)
                     continue;
                  }

                h = obj_coff_sym_hashes (input_bfd)[irel->r_symndx];
                if (h != NULL)
                  {
                    /* This is a global symbol.  */
                    if (h->indx >= 0)
                     irel->r_symndx = h->indx;
                    else
                     {
                       /* This symbol is being written at the end
                          of the file, and we do not yet know the
                          symbol index.  We save the pointer to the
                          hash table entry in the rel_hash list.
                          We set the indx field to -2 to indicate
                          that this symbol must not be stripped.  */
                       *rel_hash = h;
                       h->indx = -2;
                     }
                  }
                else
                  {
                    long indx;

                    indx = finfo->sym_indices[irel->r_symndx];
                    if (indx != -1)
                     irel->r_symndx = indx;
                    else
                     {
                       struct internal_syment *is;
                       const char *name;
                       char buf[SYMNMLEN + 1];

                       /* This reloc is against a symbol we are
                             stripping.  This should have been handled
                          by the 'dont_skip_symbol' code in the while
                          loop at the top of this function.  */
                       is = finfo->internal_syms + irel->r_symndx;

                       name = (_bfd_coff_internal_syment_name
                              (input_bfd, is, buf));
                       if (name == NULL)
                         return FALSE;

                       if (! ((*finfo->info->callbacks->unattached_reloc)
                             (finfo->info, name, input_bfd, o,
                              irel->r_vaddr)))
                         return FALSE;
                     }
                  }
              }

             o->output_section->reloc_count += o->reloc_count;
           }
       }

      /* Write out the modified section contents.  */
      if (secdata == NULL || secdata->stab_info == NULL)
       {
         file_ptr loc = o->output_offset * bfd_octets_per_byte (output_bfd);
         if (! bfd_set_section_contents (output_bfd, o->output_section,
                                     contents, loc, o->size))
           return FALSE;
       }
      else
       {
         if (! (_bfd_write_section_stabs
               (output_bfd, &coff_hash_table (finfo->info)->stab_info,
                o, &secdata->stab_info, contents)))
           return FALSE;
       }
    }

  if (! finfo->info->keep_memory
      && ! _bfd_coff_free_symbols (input_bfd))
    return FALSE;

  return TRUE;
}

Definition at line 396 of file coffgen.c.

{
  bfd_size_type relsz;
  bfd_byte *free_external = NULL;
  struct internal_reloc *free_internal = NULL;
  bfd_byte *erel;
  bfd_byte *erel_end;
  struct internal_reloc *irel;
  bfd_size_type amt;

  if (coff_section_data (abfd, sec) != NULL
      && coff_section_data (abfd, sec)->relocs != NULL)
    {
      if (! require_internal)
       return coff_section_data (abfd, sec)->relocs;
      memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs,
             sec->reloc_count * sizeof (struct internal_reloc));
      return internal_relocs;
    }

  relsz = bfd_coff_relsz (abfd);

  amt = sec->reloc_count * relsz;
  if (external_relocs == NULL)
    {
      free_external = bfd_malloc (amt);
      if (free_external == NULL && sec->reloc_count > 0)
       goto error_return;
      external_relocs = free_external;
    }

  if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
      || bfd_bread (external_relocs, amt, abfd) != amt)
    goto error_return;

  if (internal_relocs == NULL)
    {
      amt = sec->reloc_count;
      amt *= sizeof (struct internal_reloc);
      free_internal = bfd_malloc (amt);
      if (free_internal == NULL && sec->reloc_count > 0)
       goto error_return;
      internal_relocs = free_internal;
    }

  /* Swap in the relocs.  */
  erel = external_relocs;
  erel_end = erel + relsz * sec->reloc_count;
  irel = internal_relocs;
  for (; erel < erel_end; erel += relsz, irel++)
    bfd_coff_swap_reloc_in (abfd, (void *) erel, (void *) irel);

  if (free_external != NULL)
    {
      free (free_external);
      free_external = NULL;
    }

  if (cache && free_internal != NULL)
    {
      if (coff_section_data (abfd, sec) == NULL)
       {
         amt = sizeof (struct coff_section_tdata);
         sec->used_by_bfd = bfd_zalloc (abfd, amt);
         if (sec->used_by_bfd == NULL)
           goto error_return;
         coff_section_data (abfd, sec)->contents = NULL;
       }
      coff_section_data (abfd, sec)->relocs = free_internal;
    }

  return internal_relocs;

 error_return:
  if (free_external != NULL)
    free (free_external);
  if (free_internal != NULL)
    free (free_internal);
  return NULL;
}

Definition at line 1469 of file coffgen.c.

{
  char extstrsize[STRING_SIZE_SIZE];
  bfd_size_type strsize;
  char *strings;
  file_ptr pos;

  if (obj_coff_strings (abfd) != NULL)
    return obj_coff_strings (abfd);

  if (obj_sym_filepos (abfd) == 0)
    {
      bfd_set_error (bfd_error_no_symbols);
      return NULL;
    }

  pos = obj_sym_filepos (abfd);
  pos += obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd);
  if (bfd_seek (abfd, pos, SEEK_SET) != 0)
    return NULL;

  if (bfd_bread (extstrsize, (bfd_size_type) sizeof extstrsize, abfd)
      != sizeof extstrsize)
    {
      if (bfd_get_error () != bfd_error_file_truncated)
       return NULL;

      /* There is no string table.  */
      strsize = STRING_SIZE_SIZE;
    }
  else
    {
#if STRING_SIZE_SIZE == 4
      strsize = H_GET_32 (abfd, extstrsize);
#else
 #error Change H_GET_32
#endif
    }

  if (strsize < STRING_SIZE_SIZE)
    {
      (*_bfd_error_handler)
       (_("%B: bad string table size %lu"), abfd, (unsigned long) strsize);
      bfd_set_error (bfd_error_bad_value);
      return NULL;
    }

  strings = bfd_malloc (strsize);
  if (strings == NULL)
    return NULL;

  if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd)
      != strsize - STRING_SIZE_SIZE)
    {
      free (strings);
      return NULL;
    }

  obj_coff_strings (abfd) = strings;

  return strings;
}

Definition at line 2694 of file cofflink.c.

{
  reloc_howto_type *howto;
  struct internal_reloc *irel;
  struct coff_link_hash_entry **rel_hash_ptr;

  howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
  if (howto == NULL)
    {
      bfd_set_error (bfd_error_bad_value);
      return FALSE;
    }

  if (link_order->u.reloc.p->addend != 0)
    {
      bfd_size_type size;
      bfd_byte *buf;
      bfd_reloc_status_type rstat;
      bfd_boolean ok;
      file_ptr loc;

      size = bfd_get_reloc_size (howto);
      buf = bfd_zmalloc (size);
      if (buf == NULL)
       return FALSE;

      rstat = _bfd_relocate_contents (howto, output_bfd,
                                  (bfd_vma) link_order->u.reloc.p->addend,\
                                  buf);
      switch (rstat)
       {
       case bfd_reloc_ok:
         break;
       default:
       case bfd_reloc_outofrange:
         abort ();
       case bfd_reloc_overflow:
         if (! ((*finfo->info->callbacks->reloc_overflow)
               (finfo->info, NULL,
                (link_order->type == bfd_section_reloc_link_order
                 ? bfd_section_name (output_bfd,
                                   link_order->u.reloc.p->u.section)
                 : link_order->u.reloc.p->u.name),
                howto->name, link_order->u.reloc.p->addend,
                (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
           {
             free (buf);
             return FALSE;
           }
         break;
       }
      loc = link_order->offset * bfd_octets_per_byte (output_bfd);
      ok = bfd_set_section_contents (output_bfd, output_section, buf,
                                     loc, size);
      free (buf);
      if (! ok)
       return FALSE;
    }

  /* Store the reloc information in the right place.  It will get
     swapped and written out at the end of the final_link routine.  */
  irel = (finfo->section_info[output_section->target_index].relocs
         + output_section->reloc_count);
  rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
                + output_section->reloc_count);

  memset (irel, 0, sizeof (struct internal_reloc));
  *rel_hash_ptr = NULL;

  irel->r_vaddr = output_section->vma + link_order->offset;

  if (link_order->type == bfd_section_reloc_link_order)
    {
      /* We need to somehow locate a symbol in the right section.  The
         symbol must either have a value of zero, or we must adjust
         the addend by the value of the symbol.  FIXME: Write this
         when we need it.  The old linker couldn't handle this anyhow.  */
      abort ();
      *rel_hash_ptr = NULL;
      irel->r_symndx = 0;
    }
  else
    {
      struct coff_link_hash_entry *h;

      h = ((struct coff_link_hash_entry *)
          bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
                                    link_order->u.reloc.p->u.name,
                                    FALSE, FALSE, TRUE));
      if (h != NULL)
       {
         if (h->indx >= 0)
           irel->r_symndx = h->indx;
         else
           {
             /* Set the index to -2 to force this symbol to get
               written out.  */
             h->indx = -2;
             *rel_hash_ptr = h;
             irel->r_symndx = 0;
           }
       }
      else
       {
         if (! ((*finfo->info->callbacks->unattached_reloc)
               (finfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
                (asection *) NULL, (bfd_vma) 0)))
           return FALSE;
         irel->r_symndx = 0;
       }
    }

  /* FIXME: Is this always right?  */
  irel->r_type = howto->type;

  /* r_size is only used on the RS/6000, which needs its own linker
     routines anyhow.  r_extern is only used for ECOFF.  */

  /* FIXME: What is the right value for r_offset?  Is zero OK?  */
  ++output_section->reloc_count;

  return TRUE;
}

Definition at line 2455 of file cofflink.c.

{
  struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
  bfd *output_bfd;
  struct internal_syment isym;
  bfd_size_type symesz;
  unsigned int i;
  file_ptr pos;

  output_bfd = finfo->output_bfd;

  if (h->root.type == bfd_link_hash_warning)
    {
      h = (struct coff_link_hash_entry *) h->root.u.i.link;
      if (h->root.type == bfd_link_hash_new)
       return TRUE;
    }

  if (h->indx >= 0)
    return TRUE;

  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:
    case bfd_link_hash_new:
    case bfd_link_hash_warning:
      abort ();
      return FALSE;

    case bfd_link_hash_undefined:
    case bfd_link_hash_undefweak:
      isym.n_scnum = N_UNDEF;
      isym.n_value = 0;
      break;

    case bfd_link_hash_defined:
    case bfd_link_hash_defweak:
      {
       asection *sec;

       sec = h->root.u.def.section->output_section;
       if (bfd_is_abs_section (sec))
         isym.n_scnum = N_ABS;
       else
         isym.n_scnum = sec->target_index;
       isym.n_value = (h->root.u.def.value
                     + h->root.u.def.section->output_offset);
       if (! obj_pe (finfo->output_bfd))
         isym.n_value += sec->vma;
      }
      break;

    case bfd_link_hash_common:
      isym.n_scnum = N_UNDEF;
      isym.n_value = h->root.u.c.size;
      break;

    case bfd_link_hash_indirect:
      /* Just ignore these.  They can't be handled anyhow.  */
      return TRUE;
    }

  if (strlen (h->root.root.string) <= SYMNMLEN)
    strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
  else
    {
      bfd_boolean hash;
      bfd_size_type indx;

      hash = TRUE;
      if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
       hash = FALSE;
      indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
                             FALSE);
      if (indx == (bfd_size_type) -1)
       {
         finfo->failed = TRUE;
         return FALSE;
       }
      isym._n._n_n._n_zeroes = 0;
      isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
    }

  isym.n_sclass = h->class;
  isym.n_type = h->type;

  if (isym.n_sclass == C_NULL)
    isym.n_sclass = C_EXT;

  /* If doing task linking and this is the pass where we convert
     defined globals to statics, then do that conversion now.  If the
     symbol is not being converted, just ignore it and it will be
     output during a later pass.  */
  if (finfo->global_to_static)
    {
      if (! IS_EXTERNAL (output_bfd, isym))
       return TRUE;

      isym.n_sclass = C_STAT;
    }

  /* When a weak symbol is not overridden by a strong one,
     turn it into an external symbol when not building a
     shared or relocatable object.  */
  if (! finfo->info->shared
      && ! finfo->info->relocatable
      && IS_WEAK_EXTERNAL (finfo->output_bfd, isym))
    isym.n_sclass = C_EXT;

  isym.n_numaux = h->numaux;

  bfd_coff_swap_sym_out (output_bfd, &isym, finfo->outsyms);

  symesz = bfd_coff_symesz (output_bfd);

  pos = obj_sym_filepos (output_bfd);
  pos += obj_raw_syment_count (output_bfd) * symesz;
  if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
      || bfd_bwrite (finfo->outsyms, symesz, output_bfd) != symesz)
    {
      finfo->failed = TRUE;
      return FALSE;
    }

  h->indx = obj_raw_syment_count (output_bfd);

  ++obj_raw_syment_count (output_bfd);

  /* Write out any associated aux entries.  Most of the aux entries
     will have been modified in _bfd_coff_link_input_bfd.  We have to
     handle section aux entries here, now that we have the final
     relocation and line number counts.  */
  for (i = 0; i < isym.n_numaux; i++)
    {
      union internal_auxent *auxp;

      auxp = h->aux + i;

      /* Look for a section aux entry here using the same tests that
         coff_swap_aux_out uses.  */
      if (i == 0
         && (isym.n_sclass == C_STAT
             || isym.n_sclass == C_HIDDEN)
         && isym.n_type == T_NULL
         && (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak))
       {
         asection *sec;

         sec = h->root.u.def.section->output_section;
         if (sec != NULL)
           {
             auxp->x_scn.x_scnlen = sec->size;

             /* For PE, an overflow on the final link reportedly does
                 not matter.  FIXME: Why not?  */
             if (sec->reloc_count > 0xffff
                && (! obj_pe (output_bfd)
                    || finfo->info->relocatable))
              (*_bfd_error_handler)
                (_("%s: %s: reloc overflow: 0x%lx > 0xffff"),
                 bfd_get_filename (output_bfd),
                 bfd_get_section_name (output_bfd, sec),
                 sec->reloc_count);

             if (sec->lineno_count > 0xffff
                && (! obj_pe (output_bfd)
                    || finfo->info->relocatable))
              (*_bfd_error_handler)
                (_("%s: warning: %s: line number overflow: 0x%lx > 0xffff"),
                 bfd_get_filename (output_bfd),
                 bfd_get_section_name (output_bfd, sec),
                 sec->lineno_count);

             auxp->x_scn.x_nreloc = sec->reloc_count;
             auxp->x_scn.x_nlinno = sec->lineno_count;
             auxp->x_scn.x_checksum = 0;
             auxp->x_scn.x_associated = 0;
             auxp->x_scn.x_comdat = 0;
           }
       }

      bfd_coff_swap_aux_out (output_bfd, auxp, isym.n_type,
                          isym.n_sclass, (int) i, isym.n_numaux,
                          finfo->outsyms);
      if (bfd_bwrite (finfo->outsyms, symesz, output_bfd) != symesz)
       {
         finfo->failed = TRUE;
         return FALSE;
       }
      ++obj_raw_syment_count (output_bfd);
    }

  return TRUE;
}

Definition at line 2664 of file cofflink.c.

{
  struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
  bfd_boolean rtnval = TRUE;
  bfd_boolean save_global_to_static;

  if (h->root.type == bfd_link_hash_warning)
    h = (struct coff_link_hash_entry *) h->root.u.i.link;

  if (h->indx < 0)
    {
      switch (h->root.type)
       {
       case bfd_link_hash_defined:
       case bfd_link_hash_defweak:
         save_global_to_static = finfo->global_to_static;
         finfo->global_to_static = TRUE;
         rtnval = _bfd_coff_write_global_sym (h, data);
         finfo->global_to_static = save_global_to_static;
         break;
       default:
         break;
       }
    }
  return (rtnval);
}

Definition at line 5324 of file xcofflink.c.

{
  bfd_size_type symesz;
  struct xcoff_final_link_info finfo;
  asection *o;
  struct bfd_link_order *p;
  bfd_size_type max_contents_size;
  bfd_size_type max_sym_count;
  bfd_size_type max_lineno_count;
  bfd_size_type max_reloc_count;
  bfd_size_type max_output_reloc_count;
  file_ptr rel_filepos;
  unsigned int relsz;
  file_ptr line_filepos;
  unsigned int linesz;
  bfd *sub;
  bfd_byte *external_relocs = NULL;
  char strbuf[STRING_SIZE_SIZE];
  file_ptr pos;
  bfd_size_type amt;

  if (info->shared)
    abfd->flags |= DYNAMIC;

  symesz = bfd_coff_symesz (abfd);

  finfo.info = info;
  finfo.output_bfd = abfd;
  finfo.strtab = NULL;
  finfo.section_info = NULL;
  finfo.last_file_index = -1;
  finfo.toc_symindx = -1;
  finfo.internal_syms = NULL;
  finfo.sym_indices = NULL;
  finfo.outsyms = NULL;
  finfo.linenos = NULL;
  finfo.contents = NULL;
  finfo.external_relocs = NULL;

  finfo.ldsym = (xcoff_hash_table (info)->loader_section->contents
               + bfd_xcoff_ldhdrsz (abfd));
  finfo.ldrel = (xcoff_hash_table (info)->loader_section->contents
               + bfd_xcoff_ldhdrsz(abfd)
               + (xcoff_hash_table (info)->ldhdr.l_nsyms
                  * bfd_xcoff_ldsymsz(abfd)));

  xcoff_data (abfd)->coff.link_info = info;

  finfo.strtab = _bfd_stringtab_init ();
  if (finfo.strtab == NULL)
    goto error_return;

  /* Count the line number and relocation entries required for the
     output file.  Determine a few maximum sizes.  */
  max_contents_size = 0;
  max_lineno_count = 0;
  max_reloc_count = 0;
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      o->reloc_count = 0;
      o->lineno_count = 0;
      for (p = o->map_head.link_order; p != NULL; p = p->next)
       {
         if (p->type == bfd_indirect_link_order)
           {
             asection *sec;

             sec = p->u.indirect.section;

             /* 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.  */
             sec->linker_mark = TRUE;

             if (info->strip == strip_none
                || info->strip == strip_some)
              o->lineno_count += sec->lineno_count;

             o->reloc_count += sec->reloc_count;

             if (sec->rawsize > max_contents_size)
              max_contents_size = sec->rawsize;
             if (sec->size > max_contents_size)
              max_contents_size = sec->size;
             if (sec->lineno_count > max_lineno_count)
              max_lineno_count = sec->lineno_count;
             if (coff_section_data (sec->owner, sec) != NULL
                && xcoff_section_data (sec->owner, sec) != NULL
                && (xcoff_section_data (sec->owner, sec)->lineno_count
                    > max_lineno_count))
              max_lineno_count =
                xcoff_section_data (sec->owner, sec)->lineno_count;
             if (sec->reloc_count > max_reloc_count)
              max_reloc_count = sec->reloc_count;
           }
         else if (p->type == bfd_section_reloc_link_order
                 || p->type == bfd_symbol_reloc_link_order)
           ++o->reloc_count;
       }
    }

  /* Compute the file positions for all the sections.  */
  if (abfd->output_has_begun)
    {
      if (xcoff_hash_table (info)->file_align != 0)
       abort ();
    }
  else
    {
      bfd_vma file_align;

      file_align = xcoff_hash_table (info)->file_align;
      if (file_align != 0)
       {
         bfd_boolean saw_contents;
         int indx;
         file_ptr sofar;

         /* Insert .pad sections before every section which has
            contents and is loaded, if it is preceded by some other
            section which has contents and is loaded.  */
         saw_contents = TRUE;
         for (o = abfd->sections; o != NULL; o = o->next)
           {
             if (strcmp (o->name, ".pad") == 0)
              saw_contents = FALSE;
             else if ((o->flags & SEC_HAS_CONTENTS) != 0
                     && (o->flags & SEC_LOAD) != 0)
              {
                if (! saw_contents)
                  saw_contents = TRUE;
                else
                  {
                    asection *n;

                    /* Create a pad section and place it before the section
                      that needs padding.  This requires unlinking and
                      relinking the bfd's section list.  */

                    n = bfd_make_section_anyway_with_flags (abfd, ".pad",
                                                       SEC_HAS_CONTENTS);
                    n->alignment_power = 0;

                    bfd_section_list_remove (abfd, n);
                    bfd_section_list_insert_before (abfd, o, n);
                    saw_contents = FALSE;
                  }
              }
           }

         /* Reset the section indices after inserting the new
            sections.  */
         indx = 0;
         for (o = abfd->sections; o != NULL; o = o->next)
           {
             ++indx;
             o->target_index = indx;
           }
         BFD_ASSERT ((unsigned int) indx == abfd->section_count);

         /* Work out appropriate sizes for the .pad sections to force
            each section to land on a page boundary.  This bit of
            code knows what compute_section_file_positions is going
            to do.  */
         sofar = bfd_coff_filhsz (abfd);
         sofar += bfd_coff_aoutsz (abfd);
         sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
         for (o = abfd->sections; o != NULL; o = o->next)
           if ((bfd_xcoff_is_reloc_count_overflow
               (abfd, (bfd_vma) o->reloc_count))
              || (bfd_xcoff_is_lineno_count_overflow
                  (abfd, (bfd_vma) o->lineno_count)))
             /* 64 does not overflow, need to check if 32 does */
             sofar += bfd_coff_scnhsz (abfd);

         for (o = abfd->sections; o != NULL; o = o->next)
           {
             if (strcmp (o->name, ".pad") == 0)
              {
                bfd_vma pageoff;

                BFD_ASSERT (o->size == 0);
                pageoff = sofar & (file_align - 1);
                if (pageoff != 0)
                  {
                    o->size = file_align - pageoff;
                    sofar += file_align - pageoff;
                    o->flags |= SEC_HAS_CONTENTS;
                  }
              }
             else
              {
                if ((o->flags & SEC_HAS_CONTENTS) != 0)
                  sofar += BFD_ALIGN (o->size,
                                   1 << o->alignment_power);
              }
           }
       }

      if (! bfd_coff_compute_section_file_positions (abfd))
       goto error_return;
    }

  /* Allocate space for the pointers we need to keep for the relocs.  */
  {
    unsigned int i;

    /* We use section_count + 1, rather than section_count, because
       the target_index fields are 1 based.  */
    amt = abfd->section_count + 1;
    amt *= sizeof (struct xcoff_link_section_info);
    finfo.section_info = bfd_malloc (amt);
    if (finfo.section_info == NULL)
      goto error_return;
    for (i = 0; i <= abfd->section_count; i++)
      {
       finfo.section_info[i].relocs = NULL;
       finfo.section_info[i].rel_hashes = NULL;
       finfo.section_info[i].toc_rel_hashes = NULL;
      }
  }

  /* Set the file positions for the relocs.  */
  rel_filepos = obj_relocbase (abfd);
  relsz = bfd_coff_relsz (abfd);
  max_output_reloc_count = 0;
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (o->reloc_count == 0)
       o->rel_filepos = 0;
      else
       {
         /* A stripped file has no relocs.  However, we still
            allocate the buffers, so that later code doesn't have to
            worry about whether we are stripping or not.  */
         if (info->strip == strip_all)
           o->rel_filepos = 0;
         else
           {
             o->flags |= SEC_RELOC;
             o->rel_filepos = rel_filepos;
             rel_filepos += o->reloc_count * relsz;
           }

         /* We don't know the indices of global symbols until we have
            written out all the local symbols.  For each section in
            the output file, we keep an array of pointers to hash
            table entries.  Each entry in the array corresponds to a
            reloc.  When we find a reloc against a global symbol, we
            set the corresponding entry in this array so that we can
            fix up the symbol index after we have written out all the
            local symbols.

            Because of this problem, we also keep the relocs in
            memory until the end of the link.  This wastes memory.
            We could backpatch the file later, I suppose, although it
            would be slow.  */
         amt = o->reloc_count;
         amt *= sizeof (struct internal_reloc);
         finfo.section_info[o->target_index].relocs = bfd_malloc (amt);

         amt = o->reloc_count;
         amt *= sizeof (struct xcoff_link_hash_entry *);
         finfo.section_info[o->target_index].rel_hashes = bfd_malloc (amt);

         if (finfo.section_info[o->target_index].relocs == NULL
             || finfo.section_info[o->target_index].rel_hashes == NULL)
           goto error_return;

         if (o->reloc_count > max_output_reloc_count)
           max_output_reloc_count = o->reloc_count;
       }
    }

  /* We now know the size of the relocs, so we can determine the file
     positions of the line numbers.  */
  line_filepos = rel_filepos;
  finfo.line_filepos = line_filepos;
  linesz = bfd_coff_linesz (abfd);
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (o->lineno_count == 0)
       o->line_filepos = 0;
      else
       {
         o->line_filepos = line_filepos;
         line_filepos += o->lineno_count * linesz;
       }

      /* Reset the reloc and lineno counts, so that we can use them to
        count the number of entries we have output so far.  */
      o->reloc_count = 0;
      o->lineno_count = 0;
    }

  obj_sym_filepos (abfd) = line_filepos;

  /* Figure out the largest number of symbols in an input BFD.  Take
     the opportunity to clear the output_has_begun fields of all the
     input BFD's.  We want at least 6 symbols, since that is the
     number which xcoff_write_global_symbol may need.  */
  max_sym_count = 6;
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
    {
      bfd_size_type sz;

      sub->output_has_begun = FALSE;
      sz = obj_raw_syment_count (sub);
      if (sz > max_sym_count)
       max_sym_count = sz;
    }

  /* Allocate some buffers used while linking.  */
  amt = max_sym_count * sizeof (struct internal_syment);
  finfo.internal_syms = bfd_malloc (amt);

  amt = max_sym_count * sizeof (long);
  finfo.sym_indices = bfd_malloc (amt);

  amt = (max_sym_count + 1) * symesz;
  finfo.outsyms = bfd_malloc (amt);

  amt = max_lineno_count * bfd_coff_linesz (abfd);
  finfo.linenos = bfd_malloc (amt);

  amt = max_contents_size;
  finfo.contents = bfd_malloc (amt);

  amt = max_reloc_count * relsz;
  finfo.external_relocs = bfd_malloc (amt);

  if ((finfo.internal_syms == NULL && max_sym_count > 0)
      || (finfo.sym_indices == NULL && max_sym_count > 0)
      || finfo.outsyms == NULL
      || (finfo.linenos == NULL && max_lineno_count > 0)
      || (finfo.contents == NULL && max_contents_size > 0)
      || (finfo.external_relocs == NULL && max_reloc_count > 0))
    goto error_return;

  obj_raw_syment_count (abfd) = 0;
  xcoff_data (abfd)->toc = (bfd_vma) -1;

  /* We now know the position of everything in the file, except that
     we don't know the size of the symbol table and therefore we don't
     know where the string table starts.  We just build the string
     table in memory as we go along.  We process all the relocations
     for a single input file at once.  */
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      for (p = o->map_head.link_order; p != NULL; p = p->next)
       {
         if (p->type == bfd_indirect_link_order
             && p->u.indirect.section->owner->xvec == abfd->xvec)
           {
             sub = p->u.indirect.section->owner;
             if (! sub->output_has_begun)
              {
                if (! xcoff_link_input_bfd (&finfo, sub))
                  goto error_return;
                sub->output_has_begun = TRUE;
              }
           }
         else if (p->type == bfd_section_reloc_link_order
                 || p->type == bfd_symbol_reloc_link_order)
           {
             if (! xcoff_reloc_link_order (abfd, &finfo, o, p))
              goto error_return;
           }
         else
           {
             if (! _bfd_default_link_order (abfd, info, o, p))
              goto error_return;
           }
       }
    }

  /* Free up the buffers used by xcoff_link_input_bfd.  */
  if (finfo.internal_syms != NULL)
    {
      free (finfo.internal_syms);
      finfo.internal_syms = NULL;
    }
  if (finfo.sym_indices != NULL)
    {
      free (finfo.sym_indices);
      finfo.sym_indices = NULL;
    }
  if (finfo.linenos != NULL)
    {
      free (finfo.linenos);
      finfo.linenos = NULL;
    }
  if (finfo.contents != NULL)
    {
      free (finfo.contents);
      finfo.contents = NULL;
    }
  if (finfo.external_relocs != NULL)
    {
      free (finfo.external_relocs);
      finfo.external_relocs = NULL;
    }

  /* The value of the last C_FILE symbol is supposed to be -1.  Write
     it out again.  */
  if (finfo.last_file_index != -1)
    {
      finfo.last_file.n_value = -(bfd_vma) 1;
      bfd_coff_swap_sym_out (abfd, (void *) &finfo.last_file,
                          (void *) finfo.outsyms);
      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0
         || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
       goto error_return;
    }

  /* Write out all the global symbols which do not come from XCOFF
     input files.  */
  xcoff_link_hash_traverse (xcoff_hash_table (info),
                         xcoff_write_global_symbol,
                         (void *) &finfo);

  if (finfo.outsyms != NULL)
    {
      free (finfo.outsyms);
      finfo.outsyms = NULL;
    }

  /* Now that we have written out all the global symbols, we know the
     symbol indices to use for relocs against them, and we can finally
     write out the relocs.  */
  amt = max_output_reloc_count * relsz;
  external_relocs = bfd_malloc (amt);
  if (external_relocs == NULL && max_output_reloc_count != 0)
    goto error_return;

  for (o = abfd->sections; o != NULL; o = o->next)
    {
      struct internal_reloc *irel;
      struct internal_reloc *irelend;
      struct xcoff_link_hash_entry **rel_hash;
      struct xcoff_toc_rel_hash *toc_rel_hash;
      bfd_byte *erel;
      bfd_size_type rel_size;

      /* A stripped file has no relocs.  */
      if (info->strip == strip_all)
       {
         o->reloc_count = 0;
         continue;
       }

      if (o->reloc_count == 0)
       continue;

      irel = finfo.section_info[o->target_index].relocs;
      irelend = irel + o->reloc_count;
      rel_hash = finfo.section_info[o->target_index].rel_hashes;
      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
       {
         if (*rel_hash != NULL)
           {
             if ((*rel_hash)->indx < 0)
              {
                if (! ((*info->callbacks->unattached_reloc)
                      (info, (*rel_hash)->root.root.string,
                       NULL, o, irel->r_vaddr)))
                  goto error_return;
                (*rel_hash)->indx = 0;
              }
             irel->r_symndx = (*rel_hash)->indx;
           }
       }

      for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
          toc_rel_hash != NULL;
          toc_rel_hash = toc_rel_hash->next)
       {
         if (toc_rel_hash->h->u.toc_indx < 0)
           {
             if (! ((*info->callbacks->unattached_reloc)
                   (info, toc_rel_hash->h->root.root.string,
                    NULL, o, toc_rel_hash->rel->r_vaddr)))
              goto error_return;
             toc_rel_hash->h->u.toc_indx = 0;
           }
         toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
       }

      /* XCOFF requires that the relocs be sorted by address.  We tend
        to produce them in the order in which their containing csects
        appear in the symbol table, which is not necessarily by
        address.  So we sort them here.  There may be a better way to
        do this.  */
      qsort ((void *) finfo.section_info[o->target_index].relocs,
            o->reloc_count, sizeof (struct internal_reloc),
            xcoff_sort_relocs);

      irel = finfo.section_info[o->target_index].relocs;
      irelend = irel + o->reloc_count;
      erel = external_relocs;
      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
       bfd_coff_swap_reloc_out (abfd, (void *) irel, (void *) erel);

      rel_size = relsz * o->reloc_count;
      if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
         || bfd_bwrite ((void *) external_relocs, rel_size, abfd) != rel_size)
       goto error_return;
    }

  if (external_relocs != NULL)
    {
      free (external_relocs);
      external_relocs = NULL;
    }

  /* Free up the section information.  */
  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
      finfo.section_info = NULL;
    }

  /* Write out the loader section contents.  */
  BFD_ASSERT ((bfd_byte *) finfo.ldrel
             == (xcoff_hash_table (info)->loader_section->contents
                + xcoff_hash_table (info)->ldhdr.l_impoff));
  o = xcoff_hash_table (info)->loader_section;
  if (! bfd_set_section_contents (abfd, o->output_section, o->contents,
                              (file_ptr) o->output_offset, o->size))
    goto error_return;

  /* Write out the magic sections.  */
  o = xcoff_hash_table (info)->linkage_section;
  if (o->size > 0
      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
                                 (file_ptr) o->output_offset,
                                 o->size))
    goto error_return;
  o = xcoff_hash_table (info)->toc_section;
  if (o->size > 0
      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
                                 (file_ptr) o->output_offset,
                                 o->size))
    goto error_return;
  o = xcoff_hash_table (info)->descriptor_section;
  if (o->size > 0
      && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
                                 (file_ptr) o->output_offset,
                                 o->size))
    goto error_return;

  /* Write out the string table.  */
  pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
  if (bfd_seek (abfd, pos, SEEK_SET) != 0)
    goto error_return;
  H_PUT_32 (abfd,
           _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
           strbuf);
  amt = STRING_SIZE_SIZE;
  if (bfd_bwrite (strbuf, amt, abfd) != amt)
    goto error_return;
  if (! _bfd_stringtab_emit (abfd, finfo.strtab))
    goto error_return;

  _bfd_stringtab_free (finfo.strtab);

  /* Write out the debugging string table.  */
  o = xcoff_hash_table (info)->debug_section;
  if (o != NULL)
    {
      struct bfd_strtab_hash *debug_strtab;

      debug_strtab = xcoff_hash_table (info)->debug_strtab;
      BFD_ASSERT (o->output_section->size - o->output_offset
                >= _bfd_stringtab_size (debug_strtab));
      pos = o->output_section->filepos + o->output_offset;
      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
       goto error_return;
      if (! _bfd_stringtab_emit (abfd, debug_strtab))
       goto error_return;
    }

  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
     not try to write out the symbols.  */
  bfd_get_symcount (abfd) = 0;

  return TRUE;

 error_return:
  if (finfo.strtab != NULL)
    _bfd_stringtab_free (finfo.strtab);

  if (finfo.section_info != NULL)
    {
      unsigned int i;

      for (i = 0; i < abfd->section_count; i++)
       {
         if (finfo.section_info[i].relocs != NULL)
           free (finfo.section_info[i].relocs);
         if (finfo.section_info[i].rel_hashes != NULL)
           free (finfo.section_info[i].rel_hashes);
       }
      free (finfo.section_info);
    }

  if (finfo.internal_syms != NULL)
    free (finfo.internal_syms);
  if (finfo.sym_indices != NULL)
    free (finfo.sym_indices);
  if (finfo.outsyms != NULL)
    free (finfo.outsyms);
  if (finfo.linenos != NULL)
    free (finfo.linenos);
  if (finfo.contents != NULL)
    free (finfo.contents);
  if (finfo.external_relocs != NULL)
    free (finfo.external_relocs);
  if (external_relocs != NULL)
    free (external_relocs);
  return FALSE;
}

Definition at line 2154 of file xcofflink.c.

{
  switch (bfd_get_format (abfd))
    {
    case bfd_object:
      return xcoff_link_add_object_symbols (abfd, info);

    case bfd_archive:
      /* If the archive has a map, do the usual search.  We then need
        to check the archive for dynamic objects, because they may not
        appear in the archive map even though they should, perhaps, be
        included.  If the archive has no map, we just consider each object
        file in turn, since that apparently is what the AIX native linker
        does.  */
      if (bfd_has_map (abfd))
       {
         if (! (_bfd_generic_link_add_archive_symbols
               (abfd, info, xcoff_link_check_archive_element)))
           return FALSE;
       }

      {
       bfd *member;

       member = bfd_openr_next_archived_file (abfd, NULL);
       while (member != NULL)
         {
           if (bfd_check_format (member, bfd_object)
              && (info->hash->creator == member->xvec)
              && (! bfd_has_map (abfd) || (member->flags & DYNAMIC) != 0))
             {
              bfd_boolean needed;

              if (! xcoff_link_check_archive_element (member, info,
                                                 &needed))
                return FALSE;
              if (needed)
                member->archive_pass = -1;
             }
           member = bfd_openr_next_archived_file (abfd, member);
         }
      }

      return TRUE;

    default:
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
    }
}

Definition at line 439 of file xcofflink.c.

{
  struct xcoff_link_hash_table *ret;
  bfd_size_type amt = sizeof (* ret);

  ret = bfd_malloc (amt);
  if (ret == NULL)
    return NULL;
  if (!_bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc,
                              sizeof (struct xcoff_link_hash_entry)))
    {
      free (ret);
      return NULL;
    }

  ret->debug_strtab = _bfd_xcoff_stringtab_init ();
  ret->debug_section = NULL;
  ret->loader_section = NULL;
  ret->ldrel_count = 0;
  memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr));
  ret->linkage_section = NULL;
  ret->toc_section = NULL;
  ret->descriptor_section = NULL;
  ret->imports = NULL;
  ret->file_align = 0;
  ret->textro = FALSE;
  ret->gc = FALSE;
  memset (ret->special_sections, 0, sizeof ret->special_sections);

  /* The linker will always generate a full a.out header.  We need to
     record that fact now, before the sizeof_headers routine could be
     called.  */
  xcoff_data (abfd)->full_aouthdr = TRUE;

  return &ret->root;
}

Definition at line 479 of file xcofflink.c.

{
  struct xcoff_link_hash_table *ret = (struct xcoff_link_hash_table *) hash;

  _bfd_stringtab_free (ret->debug_strtab);
  bfd_hash_table_free (&ret->root.table);
  free (ret);
}

Definition at line 306 of file xcofflink.c.

{
  asection *lsec;
  bfd_byte *contents;
  struct internal_ldhdr ldhdr;
  arelent *relbuf;
  bfd_byte *elrel, *elrelend;

  if ((abfd->flags & DYNAMIC) == 0)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return -1;
    }

  lsec = bfd_get_section_by_name (abfd, ".loader");
  if (lsec == NULL)
    {
      bfd_set_error (bfd_error_no_symbols);
      return -1;
    }

  if (! xcoff_get_section_contents (abfd, lsec))
    return -1;
  contents = coff_section_data (abfd, lsec)->contents;

  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

  relbuf = bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent));
  if (relbuf == NULL)
    return -1;

  elrel = contents + bfd_xcoff_loader_reloc_offset(abfd, &ldhdr);

  elrelend = elrel + ldhdr.l_nreloc * bfd_xcoff_ldrelsz(abfd);
  for (; elrel < elrelend; elrel += bfd_xcoff_ldrelsz(abfd), relbuf++,
        prelocs++)
    {
      struct internal_ldrel ldrel;

      bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);

      if (ldrel.l_symndx >= 3)
       relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
      else
       {
         const char *name;
         asection *sec;

         switch (ldrel.l_symndx)
           {
           case 0:
             name = ".text";
             break;
           case 1:
             name = ".data";
             break;
           case 2:
             name = ".bss";
             break;
           default:
             abort ();
             break;
           }

         sec = bfd_get_section_by_name (abfd, name);
         if (sec == NULL)
           {
             bfd_set_error (bfd_error_bad_value);
             return -1;
           }

         relbuf->sym_ptr_ptr = sec->symbol_ptr_ptr;
       }

      relbuf->address = ldrel.l_vaddr;
      relbuf->addend = 0;

      /* Most dynamic relocs have the same type.  FIXME: This is only
        correct if ldrel.l_rtype == 0.  In other cases, we should use
        a different howto.  */
      relbuf->howto = bfd_xcoff_dynamic_reloc_howto(abfd);

      /* FIXME: We have no way to record the l_rsecnm field.  */

      *prelocs = relbuf;
    }

  *prelocs = NULL;

  return ldhdr.l_nreloc;
}

Definition at line 190 of file xcofflink.c.

{
  asection *lsec;
  bfd_byte *contents;
  struct internal_ldhdr ldhdr;
  const char *strings;
  bfd_byte *elsym, *elsymend;
  coff_symbol_type *symbuf;

  if ((abfd->flags & DYNAMIC) == 0)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return -1;
    }

  lsec = bfd_get_section_by_name (abfd, ".loader");
  if (lsec == NULL)
    {
      bfd_set_error (bfd_error_no_symbols);
      return -1;
    }

  if (! xcoff_get_section_contents (abfd, lsec))
    return -1;
  contents = coff_section_data (abfd, lsec)->contents;

  coff_section_data (abfd, lsec)->keep_contents = TRUE;

  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

  strings = (char *) contents + ldhdr.l_stoff;

  symbuf = bfd_zalloc (abfd, ldhdr.l_nsyms * sizeof (* symbuf));
  if (symbuf == NULL)
    return -1;

  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);

  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd), symbuf++, psyms++)
    {
      struct internal_ldsym ldsym;

      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

      symbuf->symbol.the_bfd = abfd;

      if (ldsym._l._l_l._l_zeroes == 0)
       symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
      else
       {
         char *c;

         c = bfd_alloc (abfd, (bfd_size_type) SYMNMLEN + 1);
         if (c == NULL)
           return -1;
         memcpy (c, ldsym._l._l_name, SYMNMLEN);
         c[SYMNMLEN] = '\0';
         symbuf->symbol.name = c;
       }

      if (ldsym.l_smclas == XMC_XO)
       symbuf->symbol.section = bfd_abs_section_ptr;
      else
       symbuf->symbol.section = coff_section_from_bfd_index (abfd,
                                                       ldsym.l_scnum);
      symbuf->symbol.value = ldsym.l_value - symbuf->symbol.section->vma;

      symbuf->symbol.flags = BSF_NO_FLAGS;
      if ((ldsym.l_smtype & L_EXPORT) != 0)
       symbuf->symbol.flags |= BSF_GLOBAL;

      /* FIXME: We have no way to record the other information stored
        with the loader symbol.  */
      *psyms = (asymbol *) symbuf;
    }

  *psyms = NULL;

  return ldhdr.l_nsyms;
}

Definition at line 275 of file xcofflink.c.

{
  asection *lsec;
  bfd_byte *contents;
  struct internal_ldhdr ldhdr;

  if ((abfd->flags & DYNAMIC) == 0)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return -1;
    }

  lsec = bfd_get_section_by_name (abfd, ".loader");
  if (lsec == NULL)
    {
      bfd_set_error (bfd_error_no_symbols);
      return -1;
    }

  if (! xcoff_get_section_contents (abfd, lsec))
    return -1;
  contents = coff_section_data (abfd, lsec)->contents;

  bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);

  return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
}

Definition at line 159 of file xcofflink.c.

{
  asection *lsec;
  bfd_byte *contents;
  struct internal_ldhdr ldhdr;

  if ((abfd->flags & DYNAMIC) == 0)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return -1;
    }

  lsec = bfd_get_section_by_name (abfd, ".loader");
  if (lsec == NULL)
    {
      bfd_set_error (bfd_error_no_symbols);
      return -1;
    }

  if (! xcoff_get_section_contents (abfd, lsec))
    return -1;
  contents = coff_section_data (abfd, lsec)->contents;

  bfd_xcoff_swap_ldhdr_in (abfd, (void *) contents, &ldhdr);

  return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
}

Definition at line 240 of file reloc16.c.

{
  /* Get enough memory to hold the stuff.  */
  bfd *input_bfd = link_order->u.indirect.section->owner;
  asection *input_section = link_order->u.indirect.section;
  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  arelent **reloc_vector;
  long reloc_count;
  bfd_size_type sz;

  if (reloc_size < 0)
    return NULL;

  /* If producing relocatable output, don't bother to relax.  */
  if (relocatable)
    return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
                                                 link_order,
                                                 data, relocatable,
                                                 symbols);

  /* Read in the section.  */
  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
    return NULL;

  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
  if (!reloc_vector && reloc_size != 0)
    return NULL;

  reloc_count = bfd_canonicalize_reloc (input_bfd,
                                   input_section,
                                   reloc_vector,
                                   symbols);
  if (reloc_count < 0)
    {
      free (reloc_vector);
      return NULL;
    }

  if (reloc_count > 0)
    {
      arelent **parent = reloc_vector;
      arelent *reloc;
      unsigned int dst_address = 0;
      unsigned int src_address = 0;
      unsigned int run;
      unsigned int idx;

      /* Find how long a run we can do.  */
      while (dst_address < link_order->size)
       {
         reloc = *parent;
         if (reloc)
           {
             /* Note that the relaxing didn't tie up the addresses in the
               relocation, so we use the original address to work out the
               run of non-relocated data.  */
             run = reloc->address - src_address;
             parent++;
           }
         else
           {
             run = link_order->size - dst_address;
           }

         /* Copy the bytes.  */
         for (idx = 0; idx < run; idx++)
           data[dst_address++] = data[src_address++];

         /* Now do the relocation.  */
         if (reloc)
           {
             bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
                                       reloc, data, &src_address,
                                       &dst_address);
           }
       }
    }
  free ((char *) reloc_vector);
  return data;
}

Definition at line 44 of file reloc16.c.

{
  bfd_vma value;
  asymbol *symbol = *(reloc->sym_ptr_ptr);
  /* A symbol holds a pointer to a section, and an offset from the
     base of the section.  To relocate, we find where the section will
     live in the output and add that in.  */

  if (bfd_is_und_section (symbol->section)
      || bfd_is_com_section (symbol->section))
    {
      struct bfd_link_hash_entry *h;

      /* The symbol is undefined in this BFD.  Look it up in the
        global linker hash table.  FIXME: This should be changed when
        we convert this stuff to use a specific final_link function
        and change the interface to bfd_relax_section to not require
        the generic symbols.  */
      h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
                                   bfd_asymbol_name (symbol),
                                   FALSE, FALSE, TRUE);
      if (h != (struct bfd_link_hash_entry *) NULL
         && (h->type == bfd_link_hash_defined
             || h->type == bfd_link_hash_defweak))
       value = (h->u.def.value
               + h->u.def.section->output_section->vma
               + h->u.def.section->output_offset);
      else if (h != (struct bfd_link_hash_entry *) NULL
              && h->type == bfd_link_hash_common)
       value = h->u.c.size;
      else
       {
         if (!((*link_info->callbacks->undefined_symbol)
              (link_info, bfd_asymbol_name (symbol),
               input_section->owner, input_section, reloc->address,
               TRUE)))
           abort ();
         value = 0;
       }
    }
  else
    {
      value = symbol->value
       + symbol->section->output_offset
       + symbol->section->output_section->vma;
    }

  /* Add the value contained in the relocation.  */
  value += reloc->addend;

  return value;
}

Here is the caller graph for this function:

Definition at line 140 of file reloc16.c.

{
  /* Get enough memory to hold the stuff.  */
  bfd *input_bfd = input_section->owner;
  unsigned *shrinks;
  unsigned shrink = 0;
  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  arelent **reloc_vector = NULL;
  long reloc_count;

  /* We only do global relaxation once.  It is not safe to do it multiple
     times (see discussion of the "shrinks" array below).  */
  *again = FALSE;

  if (reloc_size < 0)
    return FALSE;

  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
  if (!reloc_vector && reloc_size > 0)
    return FALSE;

  /* Get the relocs and think about them.  */
  reloc_count =
    bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
                         _bfd_generic_link_get_symbols (input_bfd));
  if (reloc_count < 0)
    {
      free (reloc_vector);
      return FALSE;
    }

  /* The reloc16.c and related relaxing code is very simple, the price
     for that simplicity is we can only call this function once for
     each section.

     So, to get the best results within that limitation, we do multiple
     relaxing passes over each section here.  That involves keeping track
     of the "shrink" at each reloc in the section.  This allows us to
     accurately determine the relative location of two relocs within
     this section.

     In theory, if we kept the "shrinks" array for each section for the
     entire link, we could use the generic relaxing code in the linker
     and get better results, particularly for jsr->bsr and 24->16 bit
     memory reference relaxations.  */

  if (reloc_count > 0)
    {
      int another_pass = 0;
      bfd_size_type amt;

      /* Allocate and initialize the shrinks array for this section.
        The last element is used as an accumulator of shrinks.  */
      amt = reloc_count + 1;
      amt *= sizeof (unsigned);
      shrinks = (unsigned *) bfd_zmalloc (amt);

      /* Loop until nothing changes in this section.  */
      do
       {
         arelent **parent;
         unsigned int i;
         long j;

         another_pass = 0;

         for (i = 0, parent = reloc_vector; *parent; parent++, i++)
           {
             /* Let the target/machine dependent code examine each reloc
               in this section and attempt to shrink it.  */
             shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
                                            shrinks[i], link_info);

             /* If it shrunk, note it in the shrinks array and set up for
               another pass.  */
             if (shrink != shrinks[i])
              {
                another_pass = 1;
                for (j = i + 1; j <= reloc_count; j++)
                  shrinks[j] += shrink - shrinks[i];
              }
           }
       }
      while (another_pass);

      shrink = shrinks[reloc_count];
      free ((char *) shrinks);
    }

  input_section->rawsize = input_section->size;
  input_section->size -= shrink;
  free ((char *) reloc_vector);
  return TRUE;
}
void bfd_perform_slip ( bfd ,
unsigned  int,
asection ,
bfd_vma   
)

Definition at line 101 of file reloc16.c.

{
  asymbol **s;

  s = _bfd_generic_link_get_symbols (abfd);
  BFD_ASSERT (s != (asymbol **) NULL);

  /* Find all symbols past this point, and make them know
     what's happened.  */
  while (*s)
    {
      asymbol *p = *s;
      if (p->section == input_section)
       {
         /* This was pointing into this section, so mangle it.  */
         if (p->value > value)
           {
             p->value -= slip;
             if (p->udata.p != NULL)
              {
                struct generic_link_hash_entry *h;

                h = (struct generic_link_hash_entry *) p->udata.p;
                BFD_ASSERT (h->root.type == bfd_link_hash_defined
                           || h->root.type == bfd_link_hash_defweak);
                h->root.u.def.value -= slip;
                BFD_ASSERT (h->root.u.def.value == p->value);
              }
           }
       }
      s++;
    }
}

Here is the caller graph for this function:

asymbol* coff_bfd_make_debug_symbol ( bfd ,
void *  ,
unsigned  long 
)

Definition at line 334 of file coffgen.c.

{
  unsigned int counter;
  coff_symbol_type *symbase;
  coff_symbol_type **location = (coff_symbol_type **) alocation;

  if (!bfd_coff_slurp_symbol_table (abfd))
    return -1;

  symbase = obj_symbols (abfd);
  counter = bfd_get_symcount (abfd);
  while (counter-- > 0)
    *location++ = symbase++;

  *location = NULL;

  return bfd_get_symcount (abfd);
}

Definition at line 485 of file coffgen.c.

{
  unsigned int limit = bfd_get_symcount (abfd);
  unsigned int i;
  int total = 0;
  asymbol **p;
  asection *s;

  if (limit == 0)
    {
      /* This may be from the backend linker, in which case the
         lineno_count in the sections is correct.  */
      for (s = abfd->sections; s != NULL; s = s->next)
       total += s->lineno_count;
      return total;
    }

  for (s = abfd->sections; s != NULL; s = s->next)
    BFD_ASSERT (s->lineno_count == 0);

  for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)
    {
      asymbol *q_maybe = *p;

      if (bfd_family_coff (bfd_asymbol_bfd (q_maybe)))
       {
         coff_symbol_type *q = coffsymbol (q_maybe);

         /* The AIX 4.1 compiler can sometimes generate line numbers
             attached to debugging symbols.  We try to simply ignore
             those here.  */
         if (q->lineno != NULL
             && q->symbol.section->owner != NULL)
           {
             /* This symbol has line numbers.  Increment the owning
                section's linenumber count.  */
             alent *l = q->lineno;

             do
              {
                asection * sec = q->symbol.section->output_section;

                /* Do not try to update fields in read-only sections.  */
                if (! bfd_is_const_section (sec))
                  sec->lineno_count ++;

                ++total;
                ++l;
              }
             while (l->line_number != 0);
           }
       }
    }

  return total;
}
bfd_boolean coff_find_inliner_info ( bfd ,
const char **  ,
const char **  ,
unsigned int  
)

Definition at line 2227 of file coffgen.c.

{
  bfd_boolean found;

  found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr,
                                    functionname_ptr, line_ptr,
                                    &coff_data(abfd)->dwarf2_find_line_info);
  return (found);
}
bfd_boolean coff_find_nearest_line ( bfd ,
asection ,
asymbol **  ,
bfd_vma  ,
const char **  ,
const char **  ,
unsigned int  
)

Definition at line 2019 of file coffgen.c.

{
  bfd_boolean found;
  unsigned int i;
  unsigned int line_base;
  coff_data_type *cof = coff_data (abfd);
  /* Run through the raw syments if available.  */
  combined_entry_type *p;
  combined_entry_type *pend;
  alent *l;
  struct coff_section_tdata *sec_data;
  bfd_size_type amt;

  /* Before looking through the symbol table, try to use a .stab
     section to find the information.  */
  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
                                        &found, filename_ptr,
                                        functionname_ptr, line_ptr,
                                        &coff_data(abfd)->line_info))
    return FALSE;

  if (found)
    return TRUE;

  /* Also try examining DWARF2 debugging information.  */
  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                 filename_ptr, functionname_ptr,
                                 line_ptr, 0,
                                 &coff_data(abfd)->dwarf2_find_line_info))
    return TRUE;

  *filename_ptr = 0;
  *functionname_ptr = 0;
  *line_ptr = 0;

  /* Don't try and find line numbers in a non coff file.  */
  if (!bfd_family_coff (abfd))
    return FALSE;

  if (cof == NULL)
    return FALSE;

  /* Find the first C_FILE symbol.  */
  p = cof->raw_syments;
  if (!p)
    return FALSE;

  pend = p + cof->raw_syment_count;
  while (p < pend)
    {
      if (p->u.syment.n_sclass == C_FILE)
       break;
      p += 1 + p->u.syment.n_numaux;
    }

  if (p < pend)
    {
      bfd_vma sec_vma;
      bfd_vma maxdiff;

      /* Look through the C_FILE symbols to find the best one.  */
      sec_vma = bfd_get_section_vma (abfd, section);
      *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
      maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
      while (1)
       {
         combined_entry_type *p2;

         for (p2 = p + 1 + p->u.syment.n_numaux;
              p2 < pend;
              p2 += 1 + p2->u.syment.n_numaux)
           {
             if (p2->u.syment.n_scnum > 0
                && (section
                    == coff_section_from_bfd_index (abfd,
                                                p2->u.syment.n_scnum)))
              break;
             if (p2->u.syment.n_sclass == C_FILE)
              {
                p2 = pend;
                break;
              }
           }

         /* We use <= MAXDIFF here so that if we get a zero length
             file, we actually use the next file entry.  */
         if (p2 < pend
             && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value
             && offset + sec_vma - (bfd_vma) p2->u.syment.n_value <= maxdiff)
           {
             *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
             maxdiff = offset + sec_vma - p2->u.syment.n_value;
           }

         /* Avoid endless loops on erroneous files by ensuring that
            we always move forward in the file.  */
         if (p >= cof->raw_syments + p->u.syment.n_value)
           break;

         p = cof->raw_syments + p->u.syment.n_value;
         if (p > pend || p->u.syment.n_sclass != C_FILE)
           break;
       }
    }

  /* Now wander though the raw linenumbers of the section.  */
  /* If we have been called on this section before, and th. e offset we
     want is further down then we can prime the lookup loop.  */
  sec_data = coff_section_data (abfd, section);
  if (sec_data != NULL
      && sec_data->i > 0
      && offset >= sec_data->offset)
    {
      i = sec_data->i;
      *functionname_ptr = sec_data->function;
      line_base = sec_data->line_base;
    }
  else
    {
      i = 0;
      line_base = 0;
    }

  if (section->lineno != NULL)
    {
      bfd_vma last_value = 0;

      l = &section->lineno[i];

      for (; i < section->lineno_count; i++)
       {
         if (l->line_number == 0)
           {
             /* Get the symbol this line number points at.  */
             coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
             if (coff->symbol.value > offset)
              break;
             *functionname_ptr = coff->symbol.name;
             last_value = coff->symbol.value;
             if (coff->native)
              {
                combined_entry_type *s = coff->native;
                s = s + 1 + s->u.syment.n_numaux;

                /* In XCOFF a debugging symbol can follow the
                   function symbol.  */
                if (s->u.syment.n_scnum == N_DEBUG)
                  s = s + 1 + s->u.syment.n_numaux;

                /* S should now point to the .bf of the function.  */
                if (s->u.syment.n_numaux)
                  {
                    /* The linenumber is stored in the auxent.  */
                    union internal_auxent *a = &((s + 1)->u.auxent);
                    line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
                    *line_ptr = line_base;
                  }
              }
           }
         else
           {
             if (l->u.offset > offset)
              break;
             *line_ptr = l->line_number + line_base - 1;
           }
         l++;
       }

      /* If we fell off the end of the loop, then assume that this
        symbol has no line number info.  Otherwise, symbols with no
        line number info get reported with the line number of the
        last line of the last symbol which does have line number
        info.  We use 0x100 as a slop to account for cases where the
        last line has executable code.  */
      if (i >= section->lineno_count
         && last_value != 0
         && offset - last_value > 0x100)
       {
         *functionname_ptr = NULL;
         *line_ptr = 0;
       }
    }

  /* Cache the results for the next call.  */
  if (sec_data == NULL && section->owner == abfd)
    {
      amt = sizeof (struct coff_section_tdata);
      section->used_by_bfd = bfd_zalloc (abfd, amt);
      sec_data = (struct coff_section_tdata *) section->used_by_bfd;
    }
  if (sec_data != NULL)
    {
      sec_data->offset = offset;
      sec_data->i = i;
      sec_data->function = *functionname_ptr;
      sec_data->line_base = line_base;
    }

  return TRUE;
}
alent* coff_get_lineno ( bfd ,
asymbol  
)

Definition at line 1558 of file coffgen.c.

{
  combined_entry_type *internal;
  combined_entry_type *internal_ptr;
  combined_entry_type *symbol_ptr;
  combined_entry_type *internal_end;
  size_t symesz;
  char *raw_src;
  char *raw_end;
  const char *string_table = NULL;
  char *debug_section = NULL;
  bfd_size_type size;

  if (obj_raw_syments (abfd) != NULL)
    return obj_raw_syments (abfd);

  size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
  internal = bfd_zalloc (abfd, size);
  if (internal == NULL && size != 0)
    return NULL;
  internal_end = internal + obj_raw_syment_count (abfd);

  if (! _bfd_coff_get_external_symbols (abfd))
    return NULL;

  raw_src = (char *) obj_coff_external_syms (abfd);

  /* Mark the end of the symbols.  */
  symesz = bfd_coff_symesz (abfd);
  raw_end = (char *) raw_src + obj_raw_syment_count (abfd) * symesz;

  /* FIXME SOMEDAY.  A string table size of zero is very weird, but
     probably possible.  If one shows up, it will probably kill us.  */

  /* Swap all the raw entries.  */
  for (internal_ptr = internal;
       raw_src < raw_end;
       raw_src += symesz, internal_ptr++)
    {

      unsigned int i;
      bfd_coff_swap_sym_in (abfd, (void *) raw_src,
                         (void *) & internal_ptr->u.syment);
      symbol_ptr = internal_ptr;

      for (i = 0;
          i < symbol_ptr->u.syment.n_numaux;
          i++)
       {
         internal_ptr++;
         raw_src += symesz;
         bfd_coff_swap_aux_in (abfd, (void *) raw_src,
                            symbol_ptr->u.syment.n_type,
                            symbol_ptr->u.syment.n_sclass,
                            (int) i, symbol_ptr->u.syment.n_numaux,
                            &(internal_ptr->u.auxent));
         coff_pointerize_aux (abfd, internal, symbol_ptr, i,
                            internal_ptr);
       }
    }

  /* Free the raw symbols, but not the strings (if we have them).  */
  obj_coff_keep_strings (abfd) = TRUE;
  if (! _bfd_coff_free_symbols (abfd))
    return NULL;

  for (internal_ptr = internal; internal_ptr < internal_end;
       internal_ptr++)
    {
      if (internal_ptr->u.syment.n_sclass == C_FILE
         && internal_ptr->u.syment.n_numaux > 0)
       {
         /* Make a file symbol point to the name in the auxent, since
            the text ".file" is redundant.  */
         if ((internal_ptr + 1)->u.auxent.x_file.x_n.x_zeroes == 0)
           {
             /* The filename is a long one, point into the string table.  */
             if (string_table == NULL)
              {
                string_table = _bfd_coff_read_string_table (abfd);
                if (string_table == NULL)
                  return NULL;
              }

             internal_ptr->u.syment._n._n_n._n_offset =
              ((long)
               (string_table
                + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
           }
         else
           {
             /* Ordinary short filename, put into memory anyway.  The
                 Microsoft PE tools sometimes store a filename in
                 multiple AUX entries.  */
             if (internal_ptr->u.syment.n_numaux > 1
                && coff_data (abfd)->pe)
              internal_ptr->u.syment._n._n_n._n_offset =
                ((long)
                 copy_name (abfd,
                           (internal_ptr + 1)->u.auxent.x_file.x_fname,
                           internal_ptr->u.syment.n_numaux * symesz));
             else
              internal_ptr->u.syment._n._n_n._n_offset =
                ((long)
                 copy_name (abfd,
                           (internal_ptr + 1)->u.auxent.x_file.x_fname,
                           (size_t) bfd_coff_filnmlen (abfd)));
           }
       }
      else
       {
         if (internal_ptr->u.syment._n._n_n._n_zeroes != 0)
           {
             /* This is a "short" name.  Make it long.  */
             size_t i;
             char *newstring;

             /* Find the length of this string without walking into memory
                that isn't ours.  */
             for (i = 0; i < 8; ++i)
              if (internal_ptr->u.syment._n._n_name[i] == '\0')
                break;

             newstring = bfd_zalloc (abfd, (bfd_size_type) (i + 1));
             if (newstring == NULL)
              return NULL;
             strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
             internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
             internal_ptr->u.syment._n._n_n._n_zeroes = 0;
           }
         else if (internal_ptr->u.syment._n._n_n._n_offset == 0)
           internal_ptr->u.syment._n._n_n._n_offset = (long int) "";
         else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
           {
             /* Long name already.  Point symbol at the string in the
                 table.  */
             if (string_table == NULL)
              {
                string_table = _bfd_coff_read_string_table (abfd);
                if (string_table == NULL)
                  return NULL;
              }
             internal_ptr->u.syment._n._n_n._n_offset =
              ((long int)
               (string_table
                + internal_ptr->u.syment._n._n_n._n_offset));
           }
         else
           {
             /* Long name in debug section.  Very similar.  */
             if (debug_section == NULL)
              debug_section = build_debug_section (abfd);
             internal_ptr->u.syment._n._n_n._n_offset = (long int)
              (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
           }
       }
      internal_ptr += internal_ptr->u.syment.n_numaux;
    }

  obj_raw_syments (abfd) = internal;
  BFD_ASSERT (obj_raw_syment_count (abfd)
             == (unsigned int) (internal_ptr - internal));

  return internal;
}

Definition at line 1725 of file coffgen.c.

{
  if (bfd_get_format (abfd) != bfd_object)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return -1;
    }
  return (asect->reloc_count + 1) * sizeof (arelent *);
}
void coff_get_symbol_info ( bfd ,
asymbol ,
symbol_info ret 
)

Definition at line 1780 of file coffgen.c.

{
  bfd_symbol_info (symbol, ret);

  if (coffsymbol (symbol)->native != NULL
      && coffsymbol (symbol)->native->fix_value)
    ret->value = coffsymbol (symbol)->native->u.syment.n_value -
      (unsigned long) obj_raw_syments (abfd);
}

Definition at line 323 of file coffgen.c.

{
  if (!bfd_coff_slurp_symbol_table (abfd))
    return -1;

  return (bfd_get_symcount (abfd) + 1) * (sizeof (coff_symbol_type *));
}

Definition at line 1736 of file coffgen.c.

{
  bfd_size_type amt = sizeof (coff_symbol_type);
  coff_symbol_type *new = bfd_zalloc (abfd, amt);

  if (new == NULL)
    return NULL;
  new->symbol.section = 0;
  new->native = 0;
  new->lineno = NULL;
  new->done_lineno = FALSE;
  new->symbol.the_bfd = abfd;

  return & new->symbol;
}
void coff_mangle_symbols ( bfd )

Definition at line 708 of file coffgen.c.

{
  unsigned int symbol_count = bfd_get_symcount (bfd_ptr);
  asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
  unsigned int symbol_index;

  for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
    {
      coff_symbol_type *coff_symbol_ptr =
      coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);

      if (coff_symbol_ptr && coff_symbol_ptr->native)
       {
         int i;
         combined_entry_type *s = coff_symbol_ptr->native;

         if (s->fix_value)
           {
             /* FIXME: We should use a union here.  */
             s->u.syment.n_value =
              (bfd_vma)((combined_entry_type *)
                       ((unsigned long) s->u.syment.n_value))->offset;
             s->fix_value = 0;
           }
         if (s->fix_line)
           {
             /* The value is the offset into the line number entries
                 for the symbol's section.  On output, the symbol's
                 section should be N_DEBUG.  */
             s->u.syment.n_value =
              (coff_symbol_ptr->symbol.section->output_section->line_filepos
               + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));
             coff_symbol_ptr->symbol.section =
              coff_section_from_bfd_index (bfd_ptr, N_DEBUG);
             BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING);
           }
         for (i = 0; i < s->u.syment.n_numaux; i++)
           {
             combined_entry_type *a = s + i + 1;
             if (a->fix_tag)
              {
                a->u.auxent.x_sym.x_tagndx.l =
                  a->u.auxent.x_sym.x_tagndx.p->offset;
                a->fix_tag = 0;
              }
             if (a->fix_end)
              {
                a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l =
                  a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset;
                a->fix_end = 0;
              }
             if (a->fix_scnlen)
              {
                a->u.auxent.x_csect.x_scnlen.l =
                  a->u.auxent.x_csect.x_scnlen.p->offset;
                a->fix_scnlen = 0;
              }
           }
       }
    }
}

Definition at line 229 of file coffgen.c.

{
  bfd_size_type filhsz;
  bfd_size_type aoutsz;
  unsigned int nscns;
  void * filehdr;
  struct internal_filehdr internal_f;
  struct internal_aouthdr internal_a;

  /* Figure out how much to read.  */
  filhsz = bfd_coff_filhsz (abfd);
  aoutsz = bfd_coff_aoutsz (abfd);

  filehdr = bfd_alloc (abfd, filhsz);
  if (filehdr == NULL)
    return NULL;
  if (bfd_bread (filehdr, filhsz, abfd) != filhsz)
    {
      if (bfd_get_error () != bfd_error_system_call)
       bfd_set_error (bfd_error_wrong_format);
      bfd_release (abfd, filehdr);
      return NULL;
    }
  bfd_coff_swap_filehdr_in (abfd, filehdr, &internal_f);
  bfd_release (abfd, filehdr);

  /* The XCOFF format has two sizes for the f_opthdr.  SMALL_AOUTSZ
     (less than aoutsz) used in object files and AOUTSZ (equal to
     aoutsz) in executables.  The bfd_coff_swap_aouthdr_in function
     expects this header to be aoutsz bytes in length, so we use that
     value in the call to bfd_alloc below.  But we must be careful to
     only read in f_opthdr bytes in the call to bfd_bread.  We should
     also attempt to catch corrupt or non-COFF binaries with a strange
     value for f_opthdr.  */
  if (! bfd_coff_bad_format_hook (abfd, &internal_f)
      || internal_f.f_opthdr > aoutsz)
    {
      bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }
  nscns = internal_f.f_nscns;

  if (internal_f.f_opthdr)
    {
      void * opthdr;

      opthdr = bfd_alloc (abfd, aoutsz);
      if (opthdr == NULL)
       return NULL;
      if (bfd_bread (opthdr, (bfd_size_type) internal_f.f_opthdr, abfd)
         != internal_f.f_opthdr)
       {
         bfd_release (abfd, opthdr);
         return NULL;
       }
      bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);
      bfd_release (abfd, opthdr);
    }

  return coff_real_object_p (abfd, nscns, &internal_f,
                          (internal_f.f_opthdr != 0
                           ? &internal_a
                           : (struct internal_aouthdr *) NULL));
}
void coff_print_symbol ( bfd ,
void *  filep,
asymbol ,
bfd_print_symbol_type   
)

Definition at line 1863 of file coffgen.c.

{
  FILE * file = (FILE *) filep;

  switch (how)
    {
    case bfd_print_symbol_name:
      fprintf (file, "%s", symbol->name);
      break;

    case bfd_print_symbol_more:
      fprintf (file, "coff %s %s",
              coffsymbol (symbol)->native ? "n" : "g",
              coffsymbol (symbol)->lineno ? "l" : " ");
      break;

    case bfd_print_symbol_all:
      if (coffsymbol (symbol)->native)
       {
         bfd_vma val;
         unsigned int aux;
         combined_entry_type *combined = coffsymbol (symbol)->native;
         combined_entry_type *root = obj_raw_syments (abfd);
         struct lineno_cache_entry *l = coffsymbol (symbol)->lineno;

         fprintf (file, "[%3ld]", (long) (combined - root));

         if (! combined->fix_value)
           val = (bfd_vma) combined->u.syment.n_value;
         else
           val = combined->u.syment.n_value - (unsigned long) root;

         fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x",
                 combined->u.syment.n_scnum,
                 combined->u.syment.n_flags,
                 combined->u.syment.n_type,
                 combined->u.syment.n_sclass,
                 combined->u.syment.n_numaux);
         fprintf_vma (file, val);
         fprintf (file, " %s", symbol->name);

         for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
           {
             combined_entry_type *auxp = combined + aux + 1;
             long tagndx;

             if (auxp->fix_tag)
              tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root;
             else
              tagndx = auxp->u.auxent.x_sym.x_tagndx.l;

             fprintf (file, "\n");

             if (bfd_coff_print_aux (abfd, file, root, combined, auxp, aux))
              continue;

             switch (combined->u.syment.n_sclass)
              {
              case C_FILE:
                fprintf (file, "File ");
                break;

              case C_STAT:
                if (combined->u.syment.n_type == T_NULL)
                  /* Probably a section symbol ?  */
                  {
                    fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d",
                            (long) auxp->u.auxent.x_scn.x_scnlen,
                            auxp->u.auxent.x_scn.x_nreloc,
                            auxp->u.auxent.x_scn.x_nlinno);
                    if (auxp->u.auxent.x_scn.x_checksum != 0
                       || auxp->u.auxent.x_scn.x_associated != 0
                       || auxp->u.auxent.x_scn.x_comdat != 0)
                     fprintf (file, " checksum 0x%lx assoc %d comdat %d",
                             auxp->u.auxent.x_scn.x_checksum,
                             auxp->u.auxent.x_scn.x_associated,
                             auxp->u.auxent.x_scn.x_comdat);
                    break;
                  }
                  /* Otherwise fall through.  */
              case C_EXT:
                if (ISFCN (combined->u.syment.n_type))
                  {
                    long next, llnos;

                    if (auxp->fix_end)
                     next = (auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p
                            - root);
                    else
                     next = auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
                    llnos = auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_lnnoptr;
                    fprintf (file,
                            "AUX tagndx %ld ttlsiz 0x%lx lnnos %ld next %ld",
                            tagndx, auxp->u.auxent.x_sym.x_misc.x_fsize,
                            llnos, next);
                    break;
                  }
                /* Otherwise fall through.  */
              default:
                fprintf (file, "AUX lnno %d size 0x%x tagndx %ld",
                        auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno,
                        auxp->u.auxent.x_sym.x_misc.x_lnsz.x_size,
                        tagndx);
                if (auxp->fix_end)
                  fprintf (file, " endndx %ld",
                          ((long)
                           (auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p
                            - root)));
                break;
              }
           }

         if (l)
           {
             fprintf (file, "\n%s :", l->u.sym->name);
             l++;
             while (l->line_number)
              {
                fprintf (file, "\n%4d : ", l->line_number);
                fprintf_vma (file, l->u.offset + symbol->section->vma);
                l++;
              }
           }
       }
      else
       {
         bfd_print_symbol_vandf (abfd, (void *) file, symbol);
         fprintf (file, " %-5s %s %s %s",
                 symbol->section->name,
                 coffsymbol (symbol)->native ? "n" : "g",
                 coffsymbol (symbol)->lineno ? "l" : " ",
                 symbol->name);
       }
    }
}

Definition at line 615 of file coffgen.c.

{
  unsigned int symbol_count = bfd_get_symcount (bfd_ptr);
  asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
  unsigned int native_index = 0;
  struct internal_syment *last_file = NULL;
  unsigned int symbol_index;

  /* COFF demands that undefined symbols come after all other symbols.
     Since we don't need to impose this extra knowledge on all our
     client programs, deal with that here.  Sort the symbol table;
     just move the undefined symbols to the end, leaving the rest
     alone.  The O'Reilly book says that defined global symbols come
     at the end before the undefined symbols, so we do that here as
     well.  */
  /* @@ Do we have some condition we could test for, so we don't always
     have to do this?  I don't think relocatability is quite right, but
     I'm not certain.  [raeburn:19920508.1711EST]  */
  {
    asymbol **newsyms;
    unsigned int i;
    bfd_size_type amt;

    amt = sizeof (asymbol *) * ((bfd_size_type) symbol_count + 1);
    newsyms = bfd_alloc (bfd_ptr, amt);
    if (!newsyms)
      return FALSE;
    bfd_ptr->outsymbols = newsyms;
    for (i = 0; i < symbol_count; i++)
      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0
         || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
             && !bfd_is_com_section (symbol_ptr_ptr[i]->section)
             && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0
                || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
                    == 0))))
       *newsyms++ = symbol_ptr_ptr[i];

    for (i = 0; i < symbol_count; i++)
      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
         && !bfd_is_und_section (symbol_ptr_ptr[i]->section)
         && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
             || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0
                && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
                    != 0))))
       *newsyms++ = symbol_ptr_ptr[i];

    *first_undef = newsyms - bfd_ptr->outsymbols;

    for (i = 0; i < symbol_count; i++)
      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
         && bfd_is_und_section (symbol_ptr_ptr[i]->section))
       *newsyms++ = symbol_ptr_ptr[i];
    *newsyms = (asymbol *) NULL;
    symbol_ptr_ptr = bfd_ptr->outsymbols;
  }

  for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
    {
      coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);
      symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;
      if (coff_symbol_ptr && coff_symbol_ptr->native)
       {
         combined_entry_type *s = coff_symbol_ptr->native;
         int i;

         if (s->u.syment.n_sclass == C_FILE)
           {
             if (last_file != NULL)
              last_file->n_value = native_index;
             last_file = &(s->u.syment);
           }
         else
           /* Modify the symbol values according to their section and
              type.  */
           fixup_symbol_value (bfd_ptr, coff_symbol_ptr, &(s->u.syment));

         for (i = 0; i < s->u.syment.n_numaux + 1; i++)
           s[i].offset = native_index++;
       }
      else
       native_index++;
    }

  obj_conv_table_size (bfd_ptr) = native_index;

  return TRUE;
}

Definition at line 297 of file coffgen.c.

{
  struct bfd_section *answer = abfd->sections;

  if (index == N_ABS)
    return bfd_abs_section_ptr;
  if (index == N_UNDEF)
    return bfd_und_section_ptr;
  if (index == N_DEBUG)
    return bfd_abs_section_ptr;

  while (answer)
    {
      if (answer->target_index == index)
       return answer;
      answer = answer->next;
    }

  /* We should not reach this point, but the SCO 3.2v4 /lib/libc_s.a
     has a bad symbol table in biglitpow.o.  */
  return bfd_und_section_ptr;
}
asymbol* coff_section_symbol ( bfd ,
char *   
)

Definition at line 2241 of file coffgen.c.

{
  size_t size;

  if (!info->relocatable)
    size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
  else
    size = bfd_coff_filhsz (abfd);

  size += abfd->section_count * bfd_coff_scnhsz (abfd);
  return size;
}

Definition at line 1262 of file coffgen.c.

{
  asection *s;
  bfd_size_type linesz;
  void * buff;

  linesz = bfd_coff_linesz (abfd);
  buff = bfd_alloc (abfd, linesz);
  if (!buff)
    return FALSE;
  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
    {
      if (s->lineno_count)
       {
         asymbol **q = abfd->outsymbols;
         if (bfd_seek (abfd, s->line_filepos, SEEK_SET) != 0)
           return FALSE;
         /* Find all the linenumbers in this section.  */
         while (*q)
           {
             asymbol *p = *q;
             if (p->section->output_section == s)
              {
                alent *l =
                BFD_SEND (bfd_asymbol_bfd (p), _get_lineno,
                         (bfd_asymbol_bfd (p), p));
                if (l)
                  {
                    /* Found a linenumber entry, output.  */
                    struct internal_lineno out;
                    memset ((void *) & out, 0, sizeof (out));
                    out.l_lnno = 0;
                    out.l_addr.l_symndx = l->u.offset;
                    bfd_coff_swap_lineno_out (abfd, &out, buff);
                    if (bfd_bwrite (buff, (bfd_size_type) linesz, abfd)
                       != linesz)
                     return FALSE;
                    l++;
                    while (l->line_number)
                     {
                       out.l_lnno = l->line_number;
                       out.l_addr.l_symndx = l->u.offset;
                       bfd_coff_swap_lineno_out (abfd, &out, buff);
                       if (bfd_bwrite (buff, (bfd_size_type) linesz, abfd)
                           != linesz)
                         return FALSE;
                       l++;
                     }
                  }
              }
             q++;
           }
       }
    }
  bfd_release (abfd, buff);
  return TRUE;
}

Definition at line 1083 of file coffgen.c.

{
  bfd_size_type string_size;
  asection *debug_string_section;
  bfd_size_type debug_string_size;
  unsigned int i;
  unsigned int limit = bfd_get_symcount (abfd);
  bfd_vma written = 0;
  asymbol **p;

  string_size = 0;
  debug_string_section = NULL;
  debug_string_size = 0;

  /* If this target supports long section names, they must be put into
     the string table.  This is supported by PE.  This code must
     handle section names just as they are handled in
     coff_write_object_contents.  */
  if (bfd_coff_long_section_names (abfd))
    {
      asection *o;

      for (o = abfd->sections; o != NULL; o = o->next)
       {
         size_t len;

         len = strlen (o->name);
         if (len > SCNNMLEN)
           string_size += len + 1;
       }
    }

  /* Seek to the right place.  */
  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
    return FALSE;

  /* Output all the symbols we have.  */
  written = 0;
  for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)
    {
      asymbol *symbol = *p;
      coff_symbol_type *c_symbol = coff_symbol_from (abfd, symbol);

      if (c_symbol == (coff_symbol_type *) NULL
         || c_symbol->native == (combined_entry_type *) NULL)
       {
         if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size,
                                   &debug_string_section,
                                   &debug_string_size))
           return FALSE;
       }
      else
       {
         if (!coff_write_native_symbol (abfd, c_symbol, &written,
                                    &string_size, &debug_string_section,
                                    &debug_string_size))
           return FALSE;
       }
    }

  obj_raw_syment_count (abfd) = written;

  /* Now write out strings.  */
  if (string_size != 0)
    {
      unsigned int size = string_size + STRING_SIZE_SIZE;
      bfd_byte buffer[STRING_SIZE_SIZE];

#if STRING_SIZE_SIZE == 4
      H_PUT_32 (abfd, size, buffer);
#else
 #error Change H_PUT_32
#endif
      if (bfd_bwrite ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd)
         != sizeof (buffer))
       return FALSE;

      /* Handle long section names.  This code must handle section
        names just as they are handled in coff_write_object_contents.  */
      if (bfd_coff_long_section_names (abfd))
       {
         asection *o;

         for (o = abfd->sections; o != NULL; o = o->next)
           {
             size_t len;

             len = strlen (o->name);
             if (len > SCNNMLEN)
              {
                if (bfd_bwrite (o->name, (bfd_size_type) (len + 1), abfd)
                    != len + 1)
                  return FALSE;
              }
           }
       }

      for (p = abfd->outsymbols, i = 0;
          i < limit;
          i++, p++)
       {
         asymbol *q = *p;
         size_t name_length = strlen (q->name);
         coff_symbol_type *c_symbol = coff_symbol_from (abfd, q);
         size_t maxlen;

         /* Figure out whether the symbol name should go in the string
            table.  Symbol names that are short enough are stored
            directly in the syment structure.  File names permit a
            different, longer, length in the syment structure.  On
            XCOFF, some symbol names are stored in the .debug section
            rather than in the string table.  */

         if (c_symbol == NULL
             || c_symbol->native == NULL)
           /* This is not a COFF symbol, so it certainly is not a
              file name, nor does it go in the .debug section.  */
           maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;

         else if (bfd_coff_symname_in_debug (abfd,
                                         &c_symbol->native->u.syment))
           /* This symbol name is in the XCOFF .debug section.
              Don't write it into the string table.  */
           maxlen = name_length;

         else if (c_symbol->native->u.syment.n_sclass == C_FILE
                 && c_symbol->native->u.syment.n_numaux > 0)
           {
             if (bfd_coff_force_symnames_in_strings (abfd))
              {
                if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6)
                  return FALSE;
              }
             maxlen = bfd_coff_filnmlen (abfd);
           }
         else
           maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;

         if (name_length > maxlen)
           {
             if (bfd_bwrite ((void *) (q->name), (bfd_size_type) name_length + 1,
                          abfd) != name_length + 1)
              return FALSE;
           }
       }
    }
  else
    {
      /* We would normally not write anything here, but we'll write
         out 4 so that any stupid coff reader which tries to read the
         string table even when there isn't one won't croak.  */
      unsigned int size = STRING_SIZE_SIZE;
      bfd_byte buffer[STRING_SIZE_SIZE];

#if STRING_SIZE_SIZE == 4
      H_PUT_32 (abfd, size, buffer);
#else
 #error Change H_PUT_32
#endif
      if (bfd_bwrite ((void *) buffer, (bfd_size_type) STRING_SIZE_SIZE, abfd)
         != STRING_SIZE_SIZE)
       return FALSE;
    }

  /* Make sure the .debug section was created to be the correct size.
     We should create it ourselves on the fly, but we don't because
     BFD won't let us write to any section until we know how large all
     the sections are.  We could still do it by making another pass
     over the symbols.  FIXME.  */
  BFD_ASSERT (debug_string_size == 0
             || (debug_string_section != (asection *) NULL
                && (BFD_ALIGN (debug_string_size,
                             1 << debug_string_section->alignment_power)
                    == debug_string_section->size)));

  return TRUE;
}