[BACK]Return to coffgen.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / bfd

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/external/gpl3/binutils.old/dist/bfd/coffgen.c between version 1.1.1.1 and 1.1.1.1.2.1

version 1.1.1.1, 2016/01/26 17:25:59 version 1.1.1.1.2.1, 2016/11/04 14:43:49
Line 1 
Line 1 
 /* Support for the generic parts of COFF, for BFD.  /* Support for the generic parts of COFF, for BFD.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,     Copyright (C) 1990-2015 Free Software Foundation, Inc.
    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009  
    Free Software Foundation, Inc.  
    Written by Cygnus Support.     Written by Cygnus Support.
   
    This file is part of BFD, the Binary File Descriptor library.     This file is part of BFD, the Binary File Descriptor library.
Line 86  make_a_section_from_file (bfd *abfd,
Line 84  make_a_section_from_file (bfd *abfd,
           strings = _bfd_coff_read_string_table (abfd);            strings = _bfd_coff_read_string_table (abfd);
           if (strings == NULL)            if (strings == NULL)
             return FALSE;              return FALSE;
           /* FIXME: For extra safety, we should make sure that            if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd))
              strindex does not run us past the end, but right now we              return FALSE;
              don't know the length of the string table.  */  
           strings += strindex;            strings += strindex;
           name = (char *) bfd_alloc (abfd,            name = (char *) bfd_alloc (abfd,
                                      (bfd_size_type) strlen (strings) + 1);                                       (bfd_size_type) strlen (strings) + 1 + 1);
           if (name == NULL)            if (name == NULL)
             return FALSE;              return FALSE;
           strcpy (name, strings);            strcpy (name, strings);
Line 102  make_a_section_from_file (bfd *abfd,
Line 99  make_a_section_from_file (bfd *abfd,
     {      {
       /* Assorted wastage to null-terminate the name, thanks AT&T! */        /* Assorted wastage to null-terminate the name, thanks AT&T! */
       name = (char *) bfd_alloc (abfd,        name = (char *) bfd_alloc (abfd,
                                  (bfd_size_type) sizeof (hdr->s_name) + 1);                                   (bfd_size_type) sizeof (hdr->s_name) + 1 + 1);
       if (name == NULL)        if (name == NULL)
         return FALSE;          return FALSE;
       strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));        strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
Line 146  make_a_section_from_file (bfd *abfd,
Line 143  make_a_section_from_file (bfd *abfd,
   if (hdr->s_scnptr != 0)    if (hdr->s_scnptr != 0)
     return_section->flags |= SEC_HAS_CONTENTS;      return_section->flags |= SEC_HAS_CONTENTS;
   
     /* Compress/decompress DWARF debug sections with names: .debug_* and
        .zdebug_*, after the section flags is set.  */
     if ((flags & SEC_DEBUGGING)
         && strlen (name) > 7
         && ((name[1] == 'd' && name[6] == '_')
             || (strlen (name) > 8 && name[1] == 'z' && name[7] == '_')))
       {
         enum { nothing, compress, decompress } action = nothing;
         char *new_name = NULL;
   
         if (bfd_is_section_compressed (abfd, return_section))
           {
             /* Compressed section.  Check if we should decompress.  */
             if ((abfd->flags & BFD_DECOMPRESS))
               action = decompress;
           }
         else if (!bfd_is_section_compressed (abfd, return_section))
           {
             /* Normal section.  Check if we should compress.  */
             if ((abfd->flags & BFD_COMPRESS) && return_section->size != 0)
               action = compress;
           }
   
         switch (action)
           {
           case nothing:
             break;
           case compress:
             if (!bfd_init_section_compress_status (abfd, return_section))
               {
                 (*_bfd_error_handler)
                   (_("%B: unable to initialize compress status for section %s"),
                    abfd, name);
                 return FALSE;
               }
             if (return_section->compress_status == COMPRESS_SECTION_DONE)
               {
                 if (name[1] != 'z')
                   {
                     unsigned int len = strlen (name);
   
                     new_name = bfd_alloc (abfd, len + 2);
                     if (new_name == NULL)
                       return FALSE;
                     new_name[0] = '.';
                     new_name[1] = 'z';
                     memcpy (new_name + 2, name + 1, len);
                   }
               }
            break;
           case decompress:
             if (!bfd_init_section_decompress_status (abfd, return_section))
               {
                 (*_bfd_error_handler)
                   (_("%B: unable to initialize decompress status for section %s"),
                    abfd, name);
                 return FALSE;
               }
             if (name[1] == 'z')
               {
                 unsigned int len = strlen (name);
   
                 new_name = bfd_alloc (abfd, len);
                 if (new_name == NULL)
                   return FALSE;
                 new_name[0] = '.';
                 memcpy (new_name + 1, name + 2, len - 1);
               }
             break;
           }
         if (new_name != NULL)
           bfd_rename_section (abfd, return_section, new_name);
       }
   
   return result;    return result;
 }  }
   
 /* Read in a COFF object and make it into a BFD.  This is used by  /* Read in a COFF object and make it into a BFD.  This is used by
    ECOFF as well.  */     ECOFF as well.  */
   const bfd_target *
 static const bfd_target *  coff_real_object_p (bfd *,
                       unsigned,
                       struct internal_filehdr *,
                       struct internal_aouthdr *);
   const bfd_target *
 coff_real_object_p (bfd *abfd,  coff_real_object_p (bfd *abfd,
                     unsigned nscns,                      unsigned nscns,
                     struct internal_filehdr *internal_f,                      struct internal_filehdr *internal_f,
Line 294  coff_object_p (bfd *abfd)
Line 369  coff_object_p (bfd *abfd)
           bfd_release (abfd, opthdr);            bfd_release (abfd, opthdr);
           return NULL;            return NULL;
         }          }
         /* PR 17512: file: 11056-1136-0.004.  */
         if (internal_f.f_opthdr < aoutsz)
           memset (((char *) opthdr) + internal_f.f_opthdr, 0, aoutsz - internal_f.f_opthdr);
   
       bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);        bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);
       bfd_release (abfd, opthdr);        bfd_release (abfd, opthdr);
     }      }
Line 392  _bfd_coff_internal_syment_name (bfd *abf
Line 471  _bfd_coff_internal_syment_name (bfd *abf
           if (strings == NULL)            if (strings == NULL)
             return NULL;              return NULL;
         }          }
         /* PR 17910: Only check for string overflow if the length has been set.
            Some DLLs, eg those produced by Visual Studio, may not set the length field.  */
         if (obj_coff_strings_len (abfd) > 0
             && sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd))
           return NULL;
       return strings + sym->_n._n_n._n_offset;        return strings + sym->_n._n_n._n_offset;
     }      }
 }  }
Line 555  coff_count_linenumbers (bfd *abfd)
Line 639  coff_count_linenumbers (bfd *abfd)
   return total;    return total;
 }  }
   
 /* Takes a bfd and a symbol, returns a pointer to the coff specific  
    area of the symbol if there is one.  */  
   
 coff_symbol_type *  
 coff_symbol_from (bfd *ignore_abfd ATTRIBUTE_UNUSED,  
                   asymbol *symbol)  
 {  
   if (!bfd_family_coff (bfd_asymbol_bfd (symbol)))  
     return (coff_symbol_type *) NULL;  
   
   if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL)  
     return (coff_symbol_type *) NULL;  
   
   return (coff_symbol_type *) symbol;  
 }  
   
 static void  static void
 fixup_symbol_value (bfd *abfd,  fixup_symbol_value (bfd *abfd,
                     coff_symbol_type *coff_symbol_ptr,                      coff_symbol_type *coff_symbol_ptr,
                     struct internal_syment *syment)                      struct internal_syment *syment)
 {  {
   /* Normalize the symbol flags.  */    /* Normalize the symbol flags.  */
   if (coff_symbol_ptr->symbol.section    if (coff_symbol_ptr->symbol.section
       && bfd_is_com_section (coff_symbol_ptr->symbol.section))        && bfd_is_com_section (coff_symbol_ptr->symbol.section))
     {      {
       /* A common symbol is undefined with a value.  */        /* A common symbol is undefined with a value.  */
Line 687  coff_renumber_symbols (bfd *bfd_ptr, int
Line 755  coff_renumber_symbols (bfd *bfd_ptr, int
   
   for (symbol_index = 0; symbol_index < symbol_count; 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]);        coff_symbol_type *coff_symbol_ptr;
   
         coff_symbol_ptr = coff_symbol_from (symbol_ptr_ptr[symbol_index]);
       symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;        symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;
       if (coff_symbol_ptr && coff_symbol_ptr->native)        if (coff_symbol_ptr && coff_symbol_ptr->native)
         {          {
           combined_entry_type *s = coff_symbol_ptr->native;            combined_entry_type *s = coff_symbol_ptr->native;
           int i;            int i;
   
             BFD_ASSERT (s->is_sym);
           if (s->u.syment.n_sclass == C_FILE)            if (s->u.syment.n_sclass == C_FILE)
             {              {
               if (last_file != NULL)                if (last_file != NULL)
Line 730  coff_mangle_symbols (bfd *bfd_ptr)
Line 801  coff_mangle_symbols (bfd *bfd_ptr)
   
   for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)    for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
     {      {
       coff_symbol_type *coff_symbol_ptr =        coff_symbol_type *coff_symbol_ptr;
       coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);  
   
         coff_symbol_ptr = coff_symbol_from (symbol_ptr_ptr[symbol_index]);
       if (coff_symbol_ptr && coff_symbol_ptr->native)        if (coff_symbol_ptr && coff_symbol_ptr->native)
         {          {
           int i;            int i;
           combined_entry_type *s = coff_symbol_ptr->native;            combined_entry_type *s = coff_symbol_ptr->native;
   
             BFD_ASSERT (s->is_sym);
           if (s->fix_value)            if (s->fix_value)
             {              {
               /* FIXME: We should use a union here.  */                /* FIXME: We should use a union here.  */
Line 761  coff_mangle_symbols (bfd *bfd_ptr)
Line 833  coff_mangle_symbols (bfd *bfd_ptr)
           for (i = 0; i < s->u.syment.n_numaux; i++)            for (i = 0; i < s->u.syment.n_numaux; i++)
             {              {
               combined_entry_type *a = s + i + 1;                combined_entry_type *a = s + i + 1;
   
                 BFD_ASSERT (! a->is_sym);
               if (a->fix_tag)                if (a->fix_tag)
                 {                  {
                   a->u.auxent.x_sym.x_tagndx.l =                    a->u.auxent.x_sym.x_tagndx.l =
Line 804  coff_fix_symbol_name (bfd *abfd,
Line 878  coff_fix_symbol_name (bfd *abfd,
     }      }
   name_length = strlen (name);    name_length = strlen (name);
   
     BFD_ASSERT (native->is_sym);
   if (native->u.syment.n_sclass == C_FILE    if (native->u.syment.n_sclass == C_FILE
       && native->u.syment.n_numaux > 0)        && native->u.syment.n_numaux > 0)
     {      {
Line 819  coff_fix_symbol_name (bfd *abfd,
Line 894  coff_fix_symbol_name (bfd *abfd,
       else        else
         strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);          strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
   
         BFD_ASSERT (! (native + 1)->is_sym);
       auxent = &(native + 1)->u.auxent;        auxent = &(native + 1)->u.auxent;
   
       filnmlen = bfd_coff_filnmlen (abfd);        filnmlen = bfd_coff_filnmlen (abfd);
Line 921  coff_write_symbol (bfd *abfd,
Line 997  coff_write_symbol (bfd *abfd,
   void * buf;    void * buf;
   bfd_size_type symesz;    bfd_size_type symesz;
   
     BFD_ASSERT (native->is_sym);
   
   if (native->u.syment.n_sclass == C_FILE)    if (native->u.syment.n_sclass == C_FILE)
     symbol->flags |= BSF_DEBUGGING;      symbol->flags |= BSF_DEBUGGING;
   
Line 961  coff_write_symbol (bfd *abfd,
Line 1039  coff_write_symbol (bfd *abfd,
         return FALSE;          return FALSE;
       for (j = 0; j < native->u.syment.n_numaux; j++)        for (j = 0; j < native->u.syment.n_numaux; j++)
         {          {
             BFD_ASSERT (! (native + j + 1)->is_sym);
           bfd_coff_swap_aux_out (abfd,            bfd_coff_swap_aux_out (abfd,
                                  &((native + j + 1)->u.auxent),                                   &((native + j + 1)->u.auxent),
                                  type, n_sclass, (int) j,                                   type, n_sclass, (int) j,
Line 1006  coff_write_alien_symbol (bfd *abfd,
Line 1085  coff_write_alien_symbol (bfd *abfd,
     {      {
       symbol->name = "";        symbol->name = "";
       if (isym != NULL)        if (isym != NULL)
         memset (isym, 0, sizeof(*isym));          memset (isym, 0, sizeof (*isym));
       return TRUE;        return TRUE;
     }      }
   native = dummy;    native = dummy;
     native->is_sym = TRUE;
     native[1].is_sym = FALSE;
   native->u.syment.n_type = T_NULL;    native->u.syment.n_type = T_NULL;
   native->u.syment.n_flags = 0;    native->u.syment.n_flags = 0;
   native->u.syment.n_numaux = 0;    native->u.syment.n_numaux = 0;
Line 1036  coff_write_alien_symbol (bfd *abfd,
Line 1117  coff_write_alien_symbol (bfd *abfd,
          name to keep it from being put in the string table.  */           name to keep it from being put in the string table.  */
       symbol->name = "";        symbol->name = "";
       if (isym != NULL)        if (isym != NULL)
         memset (isym, 0, sizeof(*isym));          memset (isym, 0, sizeof (*isym));
       return TRUE;        return TRUE;
     }      }
   else    else
Line 1050  coff_write_alien_symbol (bfd *abfd,
Line 1131  coff_write_alien_symbol (bfd *abfd,
       /* Copy the any flags from the file header into the symbol.        /* Copy the any flags from the file header into the symbol.
          FIXME: Why?  */           FIXME: Why?  */
       {        {
         coff_symbol_type *c = coff_symbol_from (abfd, symbol);          coff_symbol_type *c = coff_symbol_from (symbol);
         if (c != (coff_symbol_type *) NULL)          if (c != (coff_symbol_type *) NULL)
           native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags;            native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags;
       }        }
Line 1095  coff_write_native_symbol (bfd *abfd,
Line 1176  coff_write_native_symbol (bfd *abfd,
       return TRUE;        return TRUE;
     }      }
   
     BFD_ASSERT (native->is_sym);
   /* If this symbol has an associated line number, we must store the    /* If this symbol has an associated line number, we must store the
      symbol index in the line number field.  We also tag the auxent to       symbol index in the line number field.  We also tag the auxent to
      point to the right place in the lineno table.  */       point to the right place in the lineno table.  */
Line 1181  coff_write_symbols (bfd *abfd)
Line 1263  coff_write_symbols (bfd *abfd)
   for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)    for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)
     {      {
       asymbol *symbol = *p;        asymbol *symbol = *p;
       coff_symbol_type *c_symbol = coff_symbol_from (abfd, symbol);        coff_symbol_type *c_symbol = coff_symbol_from (symbol);
   
       if (c_symbol == (coff_symbol_type *) NULL        if (c_symbol == (coff_symbol_type *) NULL
           || c_symbol->native == (combined_entry_type *) NULL)            || c_symbol->native == (combined_entry_type *) NULL)
Line 1204  coff_write_symbols (bfd *abfd)
Line 1286  coff_write_symbols (bfd *abfd)
                  symbol which has no associated section and we do not have to                   symbol which has no associated section and we do not have to
                  worry about this, all we need to know is that it is local.  */                   worry about this, all we need to know is that it is local.  */
               current_error_handler = bfd_set_error_handler (null_error_handler);                current_error_handler = bfd_set_error_handler (null_error_handler);
                 BFD_ASSERT (c_symbol->native->is_sym);
               sym_class = bfd_coff_classify_symbol (abfd,                sym_class = bfd_coff_classify_symbol (abfd,
                                                    &c_symbol->native->u.syment);                                                      &c_symbol->native->u.syment);
               (void) bfd_set_error_handler (current_error_handler);                (void) bfd_set_error_handler (current_error_handler);
   
               n_sclass = &c_symbol->native->u.syment.n_sclass;                n_sclass = &c_symbol->native->u.syment.n_sclass;
Line 1280  coff_write_symbols (bfd *abfd)
Line 1363  coff_write_symbols (bfd *abfd)
         {          {
           asymbol *q = *p;            asymbol *q = *p;
           size_t name_length = strlen (q->name);            size_t name_length = strlen (q->name);
           coff_symbol_type *c_symbol = coff_symbol_from (abfd, q);            coff_symbol_type *c_symbol = coff_symbol_from (q);
           size_t maxlen;            size_t maxlen;
   
           /* Figure out whether the symbol name should go in the string            /* Figure out whether the symbol name should go in the string
Line 1296  coff_write_symbols (bfd *abfd)
Line 1379  coff_write_symbols (bfd *abfd)
                file name, nor does it go in the .debug section.  */                 file name, nor does it go in the .debug section.  */
             maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;              maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
   
             else if (! c_symbol->native->is_sym)
               maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
   
           else if (bfd_coff_symname_in_debug (abfd,            else if (bfd_coff_symname_in_debug (abfd,
                                               &c_symbol->native->u.syment))                                                &c_symbol->native->u.syment))
             /* This symbol name is in the XCOFF .debug section.              /* This symbol name is in the XCOFF .debug section.
Line 1386  coff_write_linenumbers (bfd *abfd)
Line 1472  coff_write_linenumbers (bfd *abfd)
                     {                      {
                       /* Found a linenumber entry, output.  */                        /* Found a linenumber entry, output.  */
                       struct internal_lineno out;                        struct internal_lineno out;
   
                       memset ((void *) & out, 0, sizeof (out));                        memset ((void *) & out, 0, sizeof (out));
                       out.l_lnno = 0;                        out.l_lnno = 0;
                       out.l_addr.l_symndx = l->u.offset;                        out.l_addr.l_symndx = l->u.offset;
Line 1433  coff_pointerize_aux (bfd *abfd,
Line 1520  coff_pointerize_aux (bfd *abfd,
   unsigned int type = symbol->u.syment.n_type;    unsigned int type = symbol->u.syment.n_type;
   unsigned int n_sclass = symbol->u.syment.n_sclass;    unsigned int n_sclass = symbol->u.syment.n_sclass;
   
     BFD_ASSERT (symbol->is_sym);
   if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)    if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
     {      {
       if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)        if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
Line 1446  coff_pointerize_aux (bfd *abfd,
Line 1534  coff_pointerize_aux (bfd *abfd,
   if (n_sclass == C_FILE)    if (n_sclass == C_FILE)
     return;      return;
   
     BFD_ASSERT (! auxent->is_sym);
   /* Otherwise patch up.  */    /* Otherwise patch up.  */
 #define N_TMASK coff_data  (abfd)->local_n_tmask  #define N_TMASK coff_data  (abfd)->local_n_tmask
 #define N_BTSHFT coff_data (abfd)->local_n_btshft  #define N_BTSHFT coff_data (abfd)->local_n_btshft
   
   if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK    if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK
        || n_sclass == C_FCN)         || n_sclass == C_FCN)
       && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)        && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
Line 1473  coff_pointerize_aux (bfd *abfd,
Line 1562  coff_pointerize_aux (bfd *abfd,
    we didn't want to go to the trouble until someone needed it.  */     we didn't want to go to the trouble until someone needed it.  */
   
 static char *  static char *
 build_debug_section (bfd *abfd)  build_debug_section (bfd *abfd, asection ** sect_return)
 {  {
   char *debug_section;    char *debug_section;
   file_ptr position;    file_ptr position;
Line 1501  build_debug_section (bfd *abfd)
Line 1590  build_debug_section (bfd *abfd)
       || bfd_bread (debug_section, sec_size, abfd) != sec_size        || bfd_bread (debug_section, sec_size, abfd) != sec_size
       || bfd_seek (abfd, position, SEEK_SET) != 0)        || bfd_seek (abfd, position, SEEK_SET) != 0)
     return NULL;      return NULL;
   
     * sect_return = sect;
   return debug_section;    return debug_section;
 }  }
   
Line 1563  _bfd_coff_get_external_symbols (bfd *abf
Line 1654  _bfd_coff_get_external_symbols (bfd *abf
   
 /* Read in the external strings.  The strings are not loaded until  /* Read in the external strings.  The strings are not loaded until
    they are needed.  This is because we have no simple way of     they are needed.  This is because we have no simple way of
    detecting a missing string table in an archive.  */     detecting a missing string table in an archive.  If the strings
      are loaded then the STRINGS and STRINGS_LEN fields in the
      coff_tdata structure will be set.  */
   
 const char *  const char *
 _bfd_coff_read_string_table (bfd *abfd)  _bfd_coff_read_string_table (bfd *abfd)
Line 1613  _bfd_coff_read_string_table (bfd *abfd)
Line 1706  _bfd_coff_read_string_table (bfd *abfd)
       return NULL;        return NULL;
     }      }
   
   strings = (char *) bfd_malloc (strsize);    strings = (char *) bfd_malloc (strsize + 1);
   if (strings == NULL)    if (strings == NULL)
     return NULL;      return NULL;
   
     /* PR 17521 file: 079-54929-0.004.
        A corrupt file could contain an index that points into the first
        STRING_SIZE_SIZE bytes of the string table, so make sure that
        they are zero.  */
     memset (strings, 0, STRING_SIZE_SIZE);
   
   if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd)    if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd)
       != strsize - STRING_SIZE_SIZE)        != strsize - STRING_SIZE_SIZE)
     {      {
Line 1625  _bfd_coff_read_string_table (bfd *abfd)
Line 1724  _bfd_coff_read_string_table (bfd *abfd)
     }      }
   
   obj_coff_strings (abfd) = strings;    obj_coff_strings (abfd) = strings;
     obj_coff_strings_len (abfd) = strsize;
     /* Terminate the string table, just in case.  */
     strings[strsize] = 0;
   return strings;    return strings;
 }  }
   
Line 1645  _bfd_coff_free_symbols (bfd *abfd)
Line 1746  _bfd_coff_free_symbols (bfd *abfd)
     {      {
       free (obj_coff_strings (abfd));        free (obj_coff_strings (abfd));
       obj_coff_strings (abfd) = NULL;        obj_coff_strings (abfd) = NULL;
         obj_coff_strings_len (abfd) = 0;
     }      }
   return TRUE;    return TRUE;
 }  }
Line 1665  coff_get_normalized_symtab (bfd *abfd)
Line 1767  coff_get_normalized_symtab (bfd *abfd)
   char *raw_src;    char *raw_src;
   char *raw_end;    char *raw_end;
   const char *string_table = NULL;    const char *string_table = NULL;
   char *debug_section = NULL;    asection * debug_sec = NULL;
     char *debug_sec_data = NULL;
   bfd_size_type size;    bfd_size_type size;
   
   if (obj_raw_syments (abfd) != NULL)    if (obj_raw_syments (abfd) != NULL)
     return obj_raw_syments (abfd);      return obj_raw_syments (abfd);
   
     if (! _bfd_coff_get_external_symbols (abfd))
       return NULL;
   
   size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);    size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
   internal = (combined_entry_type *) bfd_zalloc (abfd, size);    internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)    if (internal == NULL && size != 0)
     return NULL;      return NULL;
   internal_end = internal + obj_raw_syment_count (abfd);    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);    raw_src = (char *) obj_coff_external_syms (abfd);
   
   /* Mark the end of the symbols.  */    /* Mark the end of the symbols.  */
Line 1694  coff_get_normalized_symtab (bfd *abfd)
Line 1797  coff_get_normalized_symtab (bfd *abfd)
        raw_src < raw_end;         raw_src < raw_end;
        raw_src += symesz, internal_ptr++)         raw_src += symesz, internal_ptr++)
     {      {
   
       unsigned int i;        unsigned int i;
   
       bfd_coff_swap_sym_in (abfd, (void *) raw_src,        bfd_coff_swap_sym_in (abfd, (void *) raw_src,
                             (void *) & internal_ptr->u.syment);                              (void *) & internal_ptr->u.syment);
       symbol_ptr = internal_ptr;        symbol_ptr = internal_ptr;
         internal_ptr->is_sym = TRUE;
   
         /* PR 17512: file: 1353-1166-0.004.  */
         if (symbol_ptr->u.syment.n_sclass == C_FILE
             && symbol_ptr->u.syment.n_numaux > 0
             && raw_src + symesz + symbol_ptr->u.syment.n_numaux
             * symesz > raw_end)
           {
             bfd_release (abfd, internal);
             return NULL;
           }
   
       for (i = 0;        for (i = 0;
            i < symbol_ptr->u.syment.n_numaux;             i < symbol_ptr->u.syment.n_numaux;
            i++)             i++)
         {          {
           internal_ptr++;            internal_ptr++;
             /* PR 17512: Prevent buffer overrun.  */
             if (internal_ptr >= internal_end)
               {
                 bfd_release (abfd, internal);
                 return NULL;
               }
   
           raw_src += symesz;            raw_src += symesz;
           bfd_coff_swap_aux_in (abfd, (void *) raw_src,            bfd_coff_swap_aux_in (abfd, (void *) raw_src,
                                 symbol_ptr->u.syment.n_type,                                  symbol_ptr->u.syment.n_type,
                                 symbol_ptr->u.syment.n_sclass,                                  symbol_ptr->u.syment.n_sclass,
                                 (int) i, symbol_ptr->u.syment.n_numaux,                                  (int) i, symbol_ptr->u.syment.n_numaux,
                                 &(internal_ptr->u.auxent));                                  &(internal_ptr->u.auxent));
   
             internal_ptr->is_sym = FALSE;
           coff_pointerize_aux (abfd, internal, symbol_ptr, i,            coff_pointerize_aux (abfd, internal, symbol_ptr, i,
                                internal_ptr);                                 internal_ptr);
         }          }
Line 1724  coff_get_normalized_symtab (bfd *abfd)
Line 1847  coff_get_normalized_symtab (bfd *abfd)
   for (internal_ptr = internal; internal_ptr < internal_end;    for (internal_ptr = internal; internal_ptr < internal_end;
        internal_ptr++)         internal_ptr++)
     {      {
         BFD_ASSERT (internal_ptr->is_sym);
   
       if (internal_ptr->u.syment.n_sclass == C_FILE        if (internal_ptr->u.syment.n_sclass == C_FILE
           && internal_ptr->u.syment.n_numaux > 0)            && internal_ptr->u.syment.n_numaux > 0)
         {          {
             combined_entry_type * aux = internal_ptr + 1;
   
           /* Make a file symbol point to the name in the auxent, since            /* Make a file symbol point to the name in the auxent, since
              the text ".file" is redundant.  */               the text ".file" is redundant.  */
           if ((internal_ptr + 1)->u.auxent.x_file.x_n.x_zeroes == 0)            BFD_ASSERT (! aux->is_sym);
   
             if (aux->u.auxent.x_file.x_n.x_zeroes == 0)
             {              {
               /* The filename is a long one, point into the string table.  */                /* The filename is a long one, point into the string table.  */
               if (string_table == NULL)                if (string_table == NULL)
Line 1739  coff_get_normalized_symtab (bfd *abfd)
Line 1868  coff_get_normalized_symtab (bfd *abfd)
                     return NULL;                      return NULL;
                 }                  }
   
               internal_ptr->u.syment._n._n_n._n_offset =                if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_offset)
                 ((bfd_hostptr_t)                    >= obj_coff_strings_len (abfd))
                  (string_table                  internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
                   + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));                else
                   internal_ptr->u.syment._n._n_n._n_offset =
                     (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_offset));
             }              }
           else            else
             {              {
Line 1752  coff_get_normalized_symtab (bfd *abfd)
Line 1883  coff_get_normalized_symtab (bfd *abfd)
               if (internal_ptr->u.syment.n_numaux > 1                if (internal_ptr->u.syment.n_numaux > 1
                   && coff_data (abfd)->pe)                    && coff_data (abfd)->pe)
                 internal_ptr->u.syment._n._n_n._n_offset =                  internal_ptr->u.syment._n._n_n._n_offset =
                   ((bfd_hostptr_t)                    (bfd_hostptr_t)
                    copy_name (abfd,                    copy_name (abfd,
                               (internal_ptr + 1)->u.auxent.x_file.x_fname,                               aux->u.auxent.x_file.x_fname,
                               internal_ptr->u.syment.n_numaux * symesz));                               internal_ptr->u.syment.n_numaux * symesz);
               else                else
                 internal_ptr->u.syment._n._n_n._n_offset =                  internal_ptr->u.syment._n._n_n._n_offset =
                   ((bfd_hostptr_t)                    ((bfd_hostptr_t)
                    copy_name (abfd,                     copy_name (abfd,
                               (internal_ptr + 1)->u.auxent.x_file.x_fname,                                aux->u.auxent.x_file.x_fname,
                               (size_t) bfd_coff_filnmlen (abfd)));                                (size_t) bfd_coff_filnmlen (abfd)));
             }              }
         }          }
Line 1797  coff_get_normalized_symtab (bfd *abfd)
Line 1928  coff_get_normalized_symtab (bfd *abfd)
                   if (string_table == NULL)                    if (string_table == NULL)
                     return NULL;                      return NULL;
                 }                  }
               internal_ptr->u.syment._n._n_n._n_offset =                if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd)
                 ((bfd_hostptr_t)                    || string_table + internal_ptr->u.syment._n._n_n._n_offset < string_table)
                  (string_table                  internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
                   + internal_ptr->u.syment._n._n_n._n_offset));                else
                   internal_ptr->u.syment._n._n_n._n_offset =
                     ((bfd_hostptr_t)
                      (string_table
                       + internal_ptr->u.syment._n._n_n._n_offset));
             }              }
           else            else
             {              {
               /* Long name in debug section.  Very similar.  */                /* Long name in debug section.  Very similar.  */
               if (debug_section == NULL)                if (debug_sec_data == NULL)
                 debug_section = build_debug_section (abfd);                  debug_sec_data = build_debug_section (abfd, & debug_sec);
               internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)                if (debug_sec_data != NULL)
                 (debug_section + internal_ptr->u.syment._n._n_n._n_offset);                  {
                     BFD_ASSERT (debug_sec != NULL);
                     /* PR binutils/17512: Catch out of range offsets into the debug data.  */
                     if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size
                         || debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset < debug_sec_data)
                       internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
                     else
                       internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
                         (debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset);
                   }
                 else
                   internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) "";
             }              }
         }          }
       internal_ptr += internal_ptr->u.syment.n_numaux;        internal_ptr += internal_ptr->u.syment.n_numaux;
Line 1841  coff_make_empty_symbol (bfd *abfd)
Line 1987  coff_make_empty_symbol (bfd *abfd)
   if (new_symbol == NULL)    if (new_symbol == NULL)
     return NULL;      return NULL;
   new_symbol->symbol.section = 0;    new_symbol->symbol.section = 0;
   new_symbol->native = 0;    new_symbol->native = NULL;
   new_symbol->lineno = NULL;    new_symbol->lineno = NULL;
   new_symbol->done_lineno = FALSE;    new_symbol->done_lineno = FALSE;
   new_symbol->symbol.the_bfd = abfd;    new_symbol->symbol.the_bfd = abfd;
Line 1867  coff_bfd_make_debug_symbol (bfd *abfd,
Line 2013  coff_bfd_make_debug_symbol (bfd *abfd,
   new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt);    new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt);
   if (!new_symbol->native)    if (!new_symbol->native)
     return NULL;      return NULL;
     new_symbol->native->is_sym = TRUE;
   new_symbol->symbol.section = bfd_abs_section_ptr;    new_symbol->symbol.section = bfd_abs_section_ptr;
   new_symbol->symbol.flags = BSF_DEBUGGING;    new_symbol->symbol.flags = BSF_DEBUGGING;
   new_symbol->lineno = NULL;    new_symbol->lineno = NULL;
   new_symbol->done_lineno = FALSE;    new_symbol->done_lineno = FALSE;
   new_symbol->symbol.the_bfd = abfd;    new_symbol->symbol.the_bfd = abfd;
   
   return & new_symbol->symbol;    return & new_symbol->symbol;
 }  }
   
Line 1882  coff_get_symbol_info (bfd *abfd, asymbol
Line 2029  coff_get_symbol_info (bfd *abfd, asymbol
   bfd_symbol_info (symbol, ret);    bfd_symbol_info (symbol, ret);
   
   if (coffsymbol (symbol)->native != NULL    if (coffsymbol (symbol)->native != NULL
       && coffsymbol (symbol)->native->fix_value)        && coffsymbol (symbol)->native->fix_value
         && coffsymbol (symbol)->native->is_sym)
     ret->value = coffsymbol (symbol)->native->u.syment.n_value -      ret->value = coffsymbol (symbol)->native->u.syment.n_value -
       (bfd_hostptr_t) obj_raw_syments (abfd);        (bfd_hostptr_t) obj_raw_syments (abfd);
 }  }
   
 /* Return the COFF syment for a symbol.  */  
   
 bfd_boolean  
 bfd_coff_get_syment (bfd *abfd,  
                      asymbol *symbol,  
                      struct internal_syment *psyment)  
 {  
   coff_symbol_type *csym;  
   
   csym = coff_symbol_from (abfd, symbol);  
   if (csym == NULL || csym->native == NULL)  
     {  
       bfd_set_error (bfd_error_invalid_operation);  
       return FALSE;  
     }  
   
   *psyment = csym->native->u.syment;  
   
   if (csym->native->fix_value)  
     psyment->n_value = psyment->n_value -  
       (bfd_hostptr_t) obj_raw_syments (abfd);  
   
   /* FIXME: We should handle fix_line here.  */  
   
   return TRUE;  
 }  
   
 /* Return the COFF auxent for a symbol.  */  
   
 bfd_boolean  
 bfd_coff_get_auxent (bfd *abfd,  
                      asymbol *symbol,  
                      int indx,  
                      union internal_auxent *pauxent)  
 {  
   coff_symbol_type *csym;  
   combined_entry_type *ent;  
   
   csym = coff_symbol_from (abfd, symbol);  
   
   if (csym == NULL  
       || csym->native == NULL  
       || indx >= csym->native->u.syment.n_numaux)  
     {  
       bfd_set_error (bfd_error_invalid_operation);  
       return FALSE;  
     }  
   
   ent = csym->native + indx + 1;  
   
   *pauxent = ent->u.auxent;  
   
   if (ent->fix_tag)  
     pauxent->x_sym.x_tagndx.l =  
       ((combined_entry_type *) pauxent->x_sym.x_tagndx.p  
        - obj_raw_syments (abfd));  
   
   if (ent->fix_end)  
     pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l =  
       ((combined_entry_type *) pauxent->x_sym.x_fcnary.x_fcn.x_endndx.p  
        - obj_raw_syments (abfd));  
   
   if (ent->fix_scnlen)  
     pauxent->x_csect.x_scnlen.l =  
       ((combined_entry_type *) pauxent->x_csect.x_scnlen.p  
        - obj_raw_syments (abfd));  
   
   return TRUE;  
 }  
   
 /* Print out information about COFF symbol.  */  /* Print out information about COFF symbol.  */
   
 void  void
Line 1990  coff_print_symbol (bfd *abfd,
Line 2068  coff_print_symbol (bfd *abfd,
   
           fprintf (file, "[%3ld]", (long) (combined - root));            fprintf (file, "[%3ld]", (long) (combined - root));
   
             /* PR 17512: file: 079-33786-0.001:0.1.  */
             if (combined < obj_raw_syments (abfd)
                 || combined >= obj_raw_syments (abfd) + obj_raw_syment_count (abfd))
               {
                 fprintf (file, _("<corrupt info> %s"), symbol->name);
                 break;
               }
   
             BFD_ASSERT (combined->is_sym);
           if (! combined->fix_value)            if (! combined->fix_value)
             val = (bfd_vma) combined->u.syment.n_value;              val = (bfd_vma) combined->u.syment.n_value;
           else            else
Line 2009  coff_print_symbol (bfd *abfd,
Line 2096  coff_print_symbol (bfd *abfd,
               combined_entry_type *auxp = combined + aux + 1;                combined_entry_type *auxp = combined + aux + 1;
               long tagndx;                long tagndx;
   
                 BFD_ASSERT (! auxp->is_sym);
               if (auxp->fix_tag)                if (auxp->fix_tag)
                 tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root;                  tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root;
               else                else
Line 2083  coff_print_symbol (bfd *abfd,
Line 2171  coff_print_symbol (bfd *abfd,
               l++;                l++;
               while (l->line_number)                while (l->line_number)
                 {                  {
                   fprintf (file, "\n%4d : ", l->line_number);                    if (l->line_number > 0)
                   bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);                      {
                         fprintf (file, "\n%4d : ", l->line_number);
                         bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);
                       }
                   l++;                    l++;
                 }                  }
             }              }
Line 2119  _bfd_coff_is_local_label_name (bfd *abfd
Line 2210  _bfd_coff_is_local_label_name (bfd *abfd
   
 bfd_boolean  bfd_boolean
 coff_find_nearest_line_with_names (bfd *abfd,  coff_find_nearest_line_with_names (bfd *abfd,
                                    const struct dwarf_debug_section *debug_sections,  
                                    asection *section,  
                                    asymbol **symbols,                                     asymbol **symbols,
                                      asection *section,
                                    bfd_vma offset,                                     bfd_vma offset,
                                    const char **filename_ptr,                                     const char **filename_ptr,
                                    const char **functionname_ptr,                                     const char **functionname_ptr,
                                    unsigned int *line_ptr)                                     unsigned int *line_ptr,
                                      const struct dwarf_debug_section *debug_sections)
 {  {
   bfd_boolean found;    bfd_boolean found;
   unsigned int i;    unsigned int i;
Line 2150  coff_find_nearest_line_with_names (bfd *
Line 2241  coff_find_nearest_line_with_names (bfd *
     return TRUE;      return TRUE;
   
   /* Also try examining DWARF2 debugging information.  */    /* Also try examining DWARF2 debugging information.  */
   if (_bfd_dwarf2_find_nearest_line (abfd, debug_sections,    if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                      section, symbols, offset,  
                                      filename_ptr, functionname_ptr,                                       filename_ptr, functionname_ptr,
                                      line_ptr, NULL, 0,                                       line_ptr, NULL, debug_sections, 0,
                                      &coff_data(abfd)->dwarf2_find_line_info))                                       &coff_data(abfd)->dwarf2_find_line_info))
     return TRUE;      return TRUE;
   
     /* If the DWARF lookup failed, but there is DWARF information available
        then the problem might be that the file has been rebased.  This tool
        changes the VMAs of all the sections, but it does not update the DWARF
        information.  So try again, using a bias against the address sought.  */
     if (coff_data (abfd)->dwarf2_find_line_info != NULL)
       {
         bfd_signed_vma bias;
   
         bias = _bfd_dwarf2_find_symbol_bias (symbols,
                                              & coff_data (abfd)->dwarf2_find_line_info);
   
         if (bias
             && _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section,
                                               offset + bias,
                                               filename_ptr, functionname_ptr,
                                               line_ptr, NULL, debug_sections, 0,
                                               &coff_data(abfd)->dwarf2_find_line_info))
           return TRUE;
       }
   
   *filename_ptr = 0;    *filename_ptr = 0;
   *functionname_ptr = 0;    *functionname_ptr = 0;
   *line_ptr = 0;    *line_ptr = 0;
Line 2176  coff_find_nearest_line_with_names (bfd *
Line 2286  coff_find_nearest_line_with_names (bfd *
   pend = p + cof->raw_syment_count;    pend = p + cof->raw_syment_count;
   while (p < pend)    while (p < pend)
     {      {
         BFD_ASSERT (p->is_sym);
       if (p->u.syment.n_sclass == C_FILE)        if (p->u.syment.n_sclass == C_FILE)
         break;          break;
       p += 1 + p->u.syment.n_numaux;        p += 1 + p->u.syment.n_numaux;
Line 2199  coff_find_nearest_line_with_names (bfd *
Line 2310  coff_find_nearest_line_with_names (bfd *
                p2 < pend;                 p2 < pend;
                p2 += 1 + p2->u.syment.n_numaux)                 p2 += 1 + p2->u.syment.n_numaux)
             {              {
                 BFD_ASSERT (p2->is_sym);
               if (p2->u.syment.n_scnum > 0                if (p2->u.syment.n_scnum > 0
                   && (section                    && (section
                       == coff_section_from_bfd_index (abfd,                        == coff_section_from_bfd_index (abfd,
Line 2210  coff_find_nearest_line_with_names (bfd *
Line 2322  coff_find_nearest_line_with_names (bfd *
                   break;                    break;
                 }                  }
             }              }
             if (p2 >= pend)
               break;
   
           file_addr = (bfd_vma) p2->u.syment.n_value;            file_addr = (bfd_vma) p2->u.syment.n_value;
           /* PR 11512: Include the section address of the function name symbol.  */            /* PR 11512: Include the section address of the function name symbol.  */
Line 2274  coff_find_nearest_line_with_names (bfd *
Line 2388  coff_find_nearest_line_with_names (bfd *
               if (coff->native)                if (coff->native)
                 {                  {
                   combined_entry_type *s = coff->native;                    combined_entry_type *s = coff->native;
   
                     BFD_ASSERT (s->is_sym);
                   s = s + 1 + s->u.syment.n_numaux;                    s = s + 1 + s->u.syment.n_numaux;
   
                   /* In XCOFF a debugging symbol can follow the                    /* In XCOFF a debugging symbol can follow the
Line 2286  coff_find_nearest_line_with_names (bfd *
Line 2402  coff_find_nearest_line_with_names (bfd *
                     {                      {
                       /* The linenumber is stored in the auxent.  */                        /* The linenumber is stored in the auxent.  */
                       union internal_auxent *a = &((s + 1)->u.auxent);                        union internal_auxent *a = &((s + 1)->u.auxent);
   
                       line_base = a->x_sym.x_misc.x_lnsz.x_lnno;                        line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
                       *line_ptr = line_base;                        *line_ptr = line_base;
                     }                      }
Line 2335  coff_find_nearest_line_with_names (bfd *
Line 2452  coff_find_nearest_line_with_names (bfd *
   
 bfd_boolean  bfd_boolean
 coff_find_nearest_line (bfd *abfd,  coff_find_nearest_line (bfd *abfd,
                         asection *section,  
                         asymbol **symbols,                          asymbol **symbols,
                           asection *section,
                         bfd_vma offset,                          bfd_vma offset,
                         const char **filename_ptr,                          const char **filename_ptr,
                         const char **functionname_ptr,                          const char **functionname_ptr,
                         unsigned int *line_ptr)                          unsigned int *line_ptr,
                           unsigned int *discriminator_ptr)
 {  {
   return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections,    if (discriminator_ptr)
                                             section, symbols, offset,      *discriminator_ptr = 0;
     return coff_find_nearest_line_with_names (abfd, symbols, section, offset,
                                             filename_ptr, functionname_ptr,                                              filename_ptr, functionname_ptr,
                                             line_ptr);                                              line_ptr, dwarf_debug_sections);
 }  }
   
 bfd_boolean  bfd_boolean
Line 2367  coff_sizeof_headers (bfd *abfd, struct b
Line 2486  coff_sizeof_headers (bfd *abfd, struct b
 {  {
   size_t size;    size_t size;
   
   if (!info->relocatable)    if (!bfd_link_relocatable (info))
     size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);      size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
   else    else
     size = bfd_coff_filhsz (abfd);      size = bfd_coff_filhsz (abfd);
Line 2385  bfd_coff_set_symbol_class (bfd *        
Line 2504  bfd_coff_set_symbol_class (bfd *        
 {  {
   coff_symbol_type * csym;    coff_symbol_type * csym;
   
   csym = coff_symbol_from (abfd, symbol);    csym = coff_symbol_from (symbol);
   if (csym == NULL)    if (csym == NULL)
     {      {
       bfd_set_error (bfd_error_invalid_operation);        bfd_set_error (bfd_error_invalid_operation);
Line 2405  bfd_coff_set_symbol_class (bfd *        
Line 2524  bfd_coff_set_symbol_class (bfd *        
       if (native == NULL)        if (native == NULL)
         return FALSE;          return FALSE;
   
         native->is_sym = TRUE;
       native->u.syment.n_type   = T_NULL;        native->u.syment.n_type   = T_NULL;
       native->u.syment.n_sclass = symbol_class;        native->u.syment.n_sclass = symbol_class;
   
Line 2440  bfd_coff_set_symbol_class (bfd *        
Line 2560  bfd_coff_set_symbol_class (bfd *        
   return TRUE;    return TRUE;
 }  }
   
 struct coff_comdat_info *  
 bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec)  
 {  
   if (bfd_get_flavour (abfd) == bfd_target_coff_flavour  
       && coff_section_data (abfd, sec) != NULL)  
     return coff_section_data (abfd, sec)->comdat;  
   else  
     return NULL;  
 }  
   
 bfd_boolean  bfd_boolean
 _bfd_coff_section_already_linked (bfd *abfd,  _bfd_coff_section_already_linked (bfd *abfd,
                                   asection *sec,                                    asection *sec,
Line 2516  _bfd_coff_section_already_linked (bfd *a
Line 2626  _bfd_coff_section_already_linked (bfd *a
     info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));      info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
   return FALSE;    return FALSE;
 }  }
   
   /* Initialize COOKIE for input bfd ABFD. */
   
   static bfd_boolean
   init_reloc_cookie (struct coff_reloc_cookie *cookie,
                      struct bfd_link_info *info ATTRIBUTE_UNUSED,
                      bfd *abfd)
   {
     /* Sometimes the symbol table does not yet have been loaded here.  */
     bfd_coff_slurp_symbol_table (abfd);
   
     cookie->abfd = abfd;
     cookie->sym_hashes = obj_coff_sym_hashes (abfd);
   
     cookie->symbols = obj_symbols (abfd);
   
     return TRUE;
   }
   
   /* Free the memory allocated by init_reloc_cookie, if appropriate.  */
   
   static void
   fini_reloc_cookie (struct coff_reloc_cookie *cookie ATTRIBUTE_UNUSED,
                      bfd *abfd ATTRIBUTE_UNUSED)
   {
     /* Nothing to do.  */
   }
   
   /* Initialize the relocation information in COOKIE for input section SEC
      of input bfd ABFD.  */
   
   static bfd_boolean
   init_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           bfd *abfd,
                           asection *sec)
   {
     if (sec->reloc_count == 0)
       {
         cookie->rels = NULL;
         cookie->relend = NULL;
         cookie->rel = NULL;
         return TRUE;
       }
   
     cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, FALSE, NULL, 0, NULL);
   
     if (cookie->rels == NULL)
       return FALSE;
   
     cookie->rel = cookie->rels;
     cookie->relend = (cookie->rels + sec->reloc_count);
     return TRUE;
   }
   
   /* Free the memory allocated by init_reloc_cookie_rels,
      if appropriate.  */
   
   static void
   fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
                           asection *sec)
   {
     if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels)
       free (cookie->rels);
   }
   
   /* Initialize the whole of COOKIE for input section SEC.  */
   
   static bfd_boolean
   init_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
                                  struct bfd_link_info *info,
                                  asection *sec)
   {
     if (!init_reloc_cookie (cookie, info, sec->owner))
       return FALSE;
   
     if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
       {
         fini_reloc_cookie (cookie, sec->owner);
         return FALSE;
       }
     return TRUE;
   }
   
   /* Free the memory allocated by init_reloc_cookie_for_section,
      if appropriate.  */
   
   static void
   fini_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
                                  asection *sec)
   {
     fini_reloc_cookie_rels (cookie, sec);
     fini_reloc_cookie (cookie, sec->owner);
   }
   
   static asection *
   _bfd_coff_gc_mark_hook (asection *sec,
                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           struct internal_reloc *rel ATTRIBUTE_UNUSED,
                           struct coff_link_hash_entry *h,
                           struct internal_syment *sym)
   {
     if (h != NULL)
       {
         switch (h->root.type)
           {
           case bfd_link_hash_defined:
           case bfd_link_hash_defweak:
             return h->root.u.def.section;
   
           case bfd_link_hash_common:
             return h->root.u.c.p->section;
   
           case bfd_link_hash_undefined:
           case bfd_link_hash_undefweak:
           default:
             break;
           }
         return NULL;
       }
   
     return coff_section_from_bfd_index (sec->owner, sym->n_scnum);
   }
   
   /* COOKIE->rel describes a relocation against section SEC, which is
      a section we've decided to keep.  Return the section that contains
      the relocation symbol, or NULL if no section contains it.  */
   
   static asection *
   _bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
                           coff_gc_mark_hook_fn gc_mark_hook,
                           struct coff_reloc_cookie *cookie)
   {
     struct coff_link_hash_entry *h;
   
     h = cookie->sym_hashes[cookie->rel->r_symndx];
     if (h != NULL)
       {
         while (h->root.type == bfd_link_hash_indirect
                || h->root.type == bfd_link_hash_warning)
           h = (struct coff_link_hash_entry *) h->root.u.i.link;
   
         return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
       }
   
     return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
                             &(cookie->symbols
                               + obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment);
   }
   
   static bfd_boolean _bfd_coff_gc_mark
     (struct bfd_link_info *, asection *, coff_gc_mark_hook_fn);
   
   /* COOKIE->rel describes a relocation against section SEC, which is
      a section we've decided to keep.  Mark the section that contains
      the relocation symbol.  */
   
   static bfd_boolean
   _bfd_coff_gc_mark_reloc (struct bfd_link_info *info,
                            asection *sec,
                            coff_gc_mark_hook_fn gc_mark_hook,
                            struct coff_reloc_cookie *cookie)
   {
     asection *rsec;
   
     rsec = _bfd_coff_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
     if (rsec && !rsec->gc_mark)
       {
         if (bfd_get_flavour (rsec->owner) != bfd_target_coff_flavour)
           rsec->gc_mark = 1;
         else if (!_bfd_coff_gc_mark (info, rsec, gc_mark_hook))
           return FALSE;
       }
     return TRUE;
   }
   
   /* The mark phase of garbage collection.  For a given section, mark
      it and any sections in this section's group, and all the sections
      which define symbols to which it refers.  */
   
   static bfd_boolean
   _bfd_coff_gc_mark (struct bfd_link_info *info,
                      asection *sec,
                      coff_gc_mark_hook_fn gc_mark_hook)
   {
     bfd_boolean ret = TRUE;
   
     sec->gc_mark = 1;
   
     /* Look through the section relocs.  */
     if ((sec->flags & SEC_RELOC) != 0
         && sec->reloc_count > 0)
       {
         struct coff_reloc_cookie cookie;
   
         if (!init_reloc_cookie_for_section (&cookie, info, sec))
           ret = FALSE;
         else
           {
             for (; cookie.rel < cookie.relend; cookie.rel++)
               {
                 if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
                   {
                     ret = FALSE;
                     break;
                   }
               }
             fini_reloc_cookie_for_section (&cookie, sec);
           }
       }
   
     return ret;
   }
   
   static bfd_boolean
   _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info,
                                     coff_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED)
   {
     bfd *ibfd;
   
     for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
       {
         asection *isec;
         bfd_boolean some_kept;
   
         if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
           continue;
   
         /* Ensure all linker created sections are kept, and see whether
            any other section is already marked.  */
         some_kept = FALSE;
         for (isec = ibfd->sections; isec != NULL; isec = isec->next)
           {
             if ((isec->flags & SEC_LINKER_CREATED) != 0)
               isec->gc_mark = 1;
             else if (isec->gc_mark)
               some_kept = TRUE;
           }
   
         /* If no section in this file will be kept, then we can
            toss out debug sections.  */
         if (!some_kept)
           continue;
   
         /* Keep debug and special sections like .comment when they are
            not part of a group, or when we have single-member groups.  */
         for (isec = ibfd->sections; isec != NULL; isec = isec->next)
           if ((isec->flags & SEC_DEBUGGING) != 0
               || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
             isec->gc_mark = 1;
       }
     return TRUE;
   }
   
   /* Sweep symbols in swept sections.  Called via coff_link_hash_traverse.  */
   
   static bfd_boolean
   coff_gc_sweep_symbol (struct coff_link_hash_entry *h,
                         void *data ATTRIBUTE_UNUSED)
   {
     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_defined
          || h->root.type == bfd_link_hash_defweak)
         && !h->root.u.def.section->gc_mark
         && !(h->root.u.def.section->owner->flags & DYNAMIC))
       {
         /* Do our best to hide the symbol.  */
         h->root.u.def.section = bfd_und_section_ptr;
         h->symbol_class = C_HIDDEN;
       }
   
     return TRUE;
   }
   
   /* The sweep phase of garbage collection.  Remove all garbage sections.  */
   
   typedef bfd_boolean (*gc_sweep_hook_fn)
     (bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *);
   
   static bfd_boolean
   coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   {
     bfd *sub;
   
     for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
       {
         asection *o;
   
         if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
           continue;
   
         for (o = sub->sections; o != NULL; o = o->next)
           {
               /* Keep debug and special sections.  */
             if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
                 || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
               o->gc_mark = 1;
             else if (CONST_STRNEQ (o->name, ".idata")
                      || CONST_STRNEQ (o->name, ".pdata")
                      || CONST_STRNEQ (o->name, ".xdata")
                      || CONST_STRNEQ (o->name, ".rsrc"))
               o->gc_mark = 1;
   
             if (o->gc_mark)
               continue;
   
             /* Skip sweeping sections already excluded.  */
             if (o->flags & SEC_EXCLUDE)
               continue;
   
             /* Since this is early in the link process, it is simple
                to remove a section from the output.  */
             o->flags |= SEC_EXCLUDE;
   
             if (info->print_gc_sections && o->size != 0)
               _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
   
   #if 0
             /* But we also have to update some of the relocation
                info we collected before.  */
             if (gc_sweep_hook
                 && (o->flags & SEC_RELOC) != 0
                 && o->reloc_count > 0
                 && !bfd_is_abs_section (o->output_section))
               {
                 struct internal_reloc *internal_relocs;
                 bfd_boolean r;
   
                 internal_relocs
                   = _bfd_coff_link_read_relocs (o->owner, o, NULL, NULL,
                                                info->keep_memory);
                 if (internal_relocs == NULL)
                   return FALSE;
   
                 r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
   
                 if (coff_section_data (o)->relocs != internal_relocs)
                   free (internal_relocs);
   
                 if (!r)
                   return FALSE;
               }
   #endif
           }
       }
   
     /* Remove the symbols that were in the swept sections from the dynamic
        symbol table.  */
     coff_link_hash_traverse (coff_hash_table (info), coff_gc_sweep_symbol,
                              NULL);
   
     return TRUE;
   }
   
   /* Keep all sections containing symbols undefined on the command-line,
      and the section containing the entry symbol.  */
   
   static void
   _bfd_coff_gc_keep (struct bfd_link_info *info)
   {
     struct bfd_sym_chain *sym;
   
     for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
       {
         struct coff_link_hash_entry *h;
   
         h = coff_link_hash_lookup (coff_hash_table (info), sym->name,
                                   FALSE, FALSE, FALSE);
   
         if (h != NULL
             && (h->root.type == bfd_link_hash_defined
                 || h->root.type == bfd_link_hash_defweak)
             && !bfd_is_abs_section (h->root.u.def.section))
           h->root.u.def.section->flags |= SEC_KEEP;
       }
   }
   
   /* Do mark and sweep of unused sections.  */
   
   bfd_boolean
   bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   {
     bfd *sub;
   
     /* FIXME: Should we implement this? */
   #if 0
     const bfd_coff_backend_data *bed = coff_backend_info (abfd);
   
     if (!bed->can_gc_sections
         || !is_coff_hash_table (info->hash))
       {
         (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
         return TRUE;
       }
   #endif
   
     _bfd_coff_gc_keep (info);
   
     /* Grovel through relocs to find out who stays ...  */
     for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
       {
         asection *o;
   
         if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
           continue;
   
         for (o = sub->sections; o != NULL; o = o->next)
           {
             if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP
                  || CONST_STRNEQ (o->name, ".vectors")
                  || CONST_STRNEQ (o->name, ".ctors")
                  || CONST_STRNEQ (o->name, ".dtors"))
                 && !o->gc_mark)
               {
                 if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook))
                   return FALSE;
               }
           }
       }
   
     /* Allow the backend to mark additional target specific sections.  */
     _bfd_coff_gc_mark_extra_sections (info, _bfd_coff_gc_mark_hook);
   
     /* ... and mark SEC_EXCLUDE for those that go.  */
     return coff_gc_sweep (abfd, info);
   }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.2.1

CVSweb <webmaster@jp.NetBSD.org>