Back to index

cell-binutils  2.17cvs20070401
stabs.c
Go to the documentation of this file.
00001 /* Stabs in sections linking support.
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
00003    2006 Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor, Cygnus Support.
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /* This file contains support for linking stabs in sections, as used
00023    on COFF and ELF.  */
00024 
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "libbfd.h"
00028 #include "aout/stab_gnu.h"
00029 #include "safe-ctype.h"
00030 
00031 /* Stabs entries use a 12 byte format:
00032      4 byte string table index
00033      1 byte stab type
00034      1 byte stab other field
00035      2 byte stab desc field
00036      4 byte stab value
00037    FIXME: This will have to change for a 64 bit object format.
00038 
00039    The stabs symbols are divided into compilation units.  For the
00040    first entry in each unit, the type of 0, the value is the length of
00041    the string table for this unit, and the desc field is the number of
00042    stabs symbols for this unit.  */
00043 
00044 #define STRDXOFF  0
00045 #define TYPEOFF   4
00046 #define OTHEROFF  5
00047 #define DESCOFF   6
00048 #define VALOFF    8
00049 #define STABSIZE  12
00050 
00051 /* A linked list of totals that we have found for a particular header
00052    file.  A total is a unique identifier for a particular BINCL...EINCL
00053    sequence of STABs that can be used to identify duplicate sequences.
00054    It consists of three fields, 'sum_chars' which is the sum of all the
00055    STABS characters; 'num_chars' which is the number of these charactes
00056    and 'symb' which is a buffer of all the symbols in the sequence.  This
00057    buffer is only checked as a last resort.  */
00058 
00059 struct stab_link_includes_totals
00060 {
00061   struct stab_link_includes_totals *next;
00062   bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
00063   bfd_vma num_chars;  /* Number of STABS characters.  */
00064   const char* symb;   /* The STABS characters themselves.  */
00065 };
00066 
00067 /* An entry in the header file hash table.  */
00068 
00069 struct stab_link_includes_entry
00070 {
00071   struct bfd_hash_entry root;
00072   /* List of totals we have found for this file.  */
00073   struct stab_link_includes_totals *totals;
00074 };
00075 
00076 /* This structure is used to hold a list of N_BINCL symbols, some of
00077    which might be converted into N_EXCL symbols.  */
00078 
00079 struct stab_excl_list
00080 {
00081   /* The next symbol to convert.  */
00082   struct stab_excl_list *next;
00083   /* The offset to this symbol in the section contents.  */
00084   bfd_size_type offset;
00085   /* The value to use for the symbol.  */
00086   bfd_vma val;
00087   /* The type of this symbol (N_BINCL or N_EXCL).  */
00088   int type;
00089 };
00090 
00091 /* This structure is stored with each .stab section.  */
00092 
00093 struct stab_section_info
00094 {
00095   /* This is a linked list of N_BINCL symbols which should be
00096      converted into N_EXCL symbols.  */
00097   struct stab_excl_list *excls;
00098 
00099   /* This is used to map input stab offsets within their sections
00100      to output stab offsets, to take into account stabs that have
00101      been deleted.  If it is NULL, the output offsets are the same
00102      as the input offsets, because no stabs have been deleted from
00103      this section.  Otherwise the i'th entry is the number of
00104      bytes of stabs that have been deleted prior to the i'th
00105      stab.  */
00106   bfd_size_type *cumulative_skips;
00107 
00108   /* This is an array of string indices.  For each stab symbol, we
00109      store the string index here.  If a stab symbol should not be
00110      included in the final output, the string index is -1.  */
00111   bfd_size_type stridxs[1];
00112 };
00113 
00114 
00115 /* The function to create a new entry in the header file hash table.  */
00116 
00117 static struct bfd_hash_entry *
00118 stab_link_includes_newfunc (struct bfd_hash_entry *entry,
00119                          struct bfd_hash_table *table,
00120                          const char *string)
00121 {
00122   struct stab_link_includes_entry *ret =
00123     (struct stab_link_includes_entry *) entry;
00124 
00125   /* Allocate the structure if it has not already been allocated by a
00126      subclass.  */
00127   if (ret == NULL)
00128     ret = bfd_hash_allocate (table,
00129                           sizeof (struct stab_link_includes_entry));
00130   if (ret == NULL)
00131     return NULL;
00132 
00133   /* Call the allocation method of the superclass.  */
00134   ret = ((struct stab_link_includes_entry *)
00135         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
00136   if (ret)
00137     /* Set local fields.  */
00138     ret->totals = NULL;
00139 
00140   return (struct bfd_hash_entry *) ret;
00141 }
00142 
00143 /* This function is called for each input file from the add_symbols
00144    pass of the linker.  */
00145 
00146 bfd_boolean
00147 _bfd_link_section_stabs (bfd *abfd,
00148                       struct stab_info *sinfo,
00149                       asection *stabsec,
00150                       asection *stabstrsec,
00151                       void * *psecinfo,
00152                       bfd_size_type *pstring_offset)
00153 {
00154   bfd_boolean first;
00155   bfd_size_type count, amt;
00156   struct stab_section_info *secinfo;
00157   bfd_byte *stabbuf = NULL;
00158   bfd_byte *stabstrbuf = NULL;
00159   bfd_byte *sym, *symend;
00160   bfd_size_type stroff, next_stroff, skip;
00161   bfd_size_type *pstridx;
00162 
00163   if (stabsec->size == 0
00164       || stabstrsec->size == 0)
00165     /* This file does not contain stabs debugging information.  */
00166     return TRUE;
00167 
00168   if (stabsec->size % STABSIZE != 0)
00169     /* Something is wrong with the format of these stab symbols.
00170        Don't try to optimize them.  */
00171     return TRUE;
00172 
00173   if ((stabstrsec->flags & SEC_RELOC) != 0)
00174     /* We shouldn't see relocations in the strings, and we aren't
00175        prepared to handle them.  */
00176     return TRUE;
00177 
00178   if (bfd_is_abs_section (stabsec->output_section)
00179       || bfd_is_abs_section (stabstrsec->output_section))
00180     /* At least one of the sections is being discarded from the
00181        link, so we should just ignore them.  */
00182     return TRUE;
00183 
00184   first = FALSE;
00185 
00186   if (sinfo->stabstr == NULL)
00187     {
00188       flagword flags;
00189 
00190       /* Initialize the stabs information we need to keep track of.  */
00191       first = TRUE;
00192       sinfo->strings = _bfd_stringtab_init ();
00193       if (sinfo->strings == NULL)
00194        goto error_return;
00195       /* Make sure the first byte is zero.  */
00196       (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
00197       if (! bfd_hash_table_init (&sinfo->includes,
00198                              stab_link_includes_newfunc,
00199                              sizeof (struct stab_link_includes_entry)))
00200        goto error_return;
00201       flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
00202               | SEC_LINKER_CREATED);
00203       sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
00204                                                     flags);
00205       if (sinfo->stabstr == NULL)
00206        goto error_return;
00207     }
00208 
00209   /* Initialize the information we are going to store for this .stab
00210      section.  */
00211   count = stabsec->size / STABSIZE;
00212 
00213   amt = sizeof (struct stab_section_info);
00214   amt += (count - 1) * sizeof (bfd_size_type);
00215   *psecinfo = bfd_alloc (abfd, amt);
00216   if (*psecinfo == NULL)
00217     goto error_return;
00218 
00219   secinfo = (struct stab_section_info *) *psecinfo;
00220   secinfo->excls = NULL;
00221   stabsec->rawsize = stabsec->size;
00222   secinfo->cumulative_skips = NULL;
00223   memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
00224 
00225   /* Read the stabs information from abfd.  */
00226   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
00227       || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
00228     goto error_return;
00229 
00230   /* Look through the stabs symbols, work out the new string indices,
00231      and identify N_BINCL symbols which can be eliminated.  */
00232   stroff = 0;
00233   /* The stabs sections can be split when
00234      -split-by-reloc/-split-by-file is used.  We must keep track of
00235      each stab section's place in the single concatenated string
00236      table.  */
00237   next_stroff = pstring_offset ? *pstring_offset : 0;
00238   skip = 0;
00239 
00240   symend = stabbuf + stabsec->size;
00241   for (sym = stabbuf, pstridx = secinfo->stridxs;
00242        sym < symend;
00243        sym += STABSIZE, ++pstridx)
00244     {
00245       bfd_size_type symstroff;
00246       int type;
00247       const char *string;
00248 
00249       if (*pstridx != 0)
00250        /* This symbol has already been handled by an N_BINCL pass.  */
00251        continue;
00252 
00253       type = sym[TYPEOFF];
00254 
00255       if (type == 0)
00256        {
00257          /* Special type 0 stabs indicate the offset to the next
00258             string table.  We only copy the very first one.  */
00259          stroff = next_stroff;
00260          next_stroff += bfd_get_32 (abfd, sym + 8);
00261          if (pstring_offset)
00262            *pstring_offset = next_stroff;
00263          if (! first)
00264            {
00265              *pstridx = (bfd_size_type) -1;
00266              ++skip;
00267              continue;
00268            }
00269          first = FALSE;
00270        }
00271 
00272       /* Store the string in the hash table, and record the index.  */
00273       symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
00274       if (symstroff >= stabstrsec->size)
00275        {
00276          (*_bfd_error_handler)
00277            (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
00278             abfd, stabsec, (long) (sym - stabbuf));
00279          bfd_set_error (bfd_error_bad_value);
00280          goto error_return;
00281        }
00282       string = (char *) stabstrbuf + symstroff;
00283       *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
00284 
00285       /* An N_BINCL symbol indicates the start of the stabs entries
00286         for a header file.  We need to scan ahead to the next N_EINCL
00287         symbol, ignoring nesting, adding up all the characters in the
00288         symbol names, not including the file numbers in types (the
00289         first number after an open parenthesis).  */
00290       if (type == (int) N_BINCL)
00291        {
00292          bfd_vma sum_chars;
00293          bfd_vma num_chars;
00294          bfd_vma buf_len = 0;
00295          char * symb;
00296          char * symb_rover;
00297          int nest;
00298          bfd_byte * incl_sym;
00299          struct stab_link_includes_entry * incl_entry;
00300          struct stab_link_includes_totals * t;
00301          struct stab_excl_list * ne;
00302 
00303          symb = symb_rover = NULL;
00304          sum_chars = num_chars = 0;
00305          nest = 0;
00306 
00307          for (incl_sym = sym + STABSIZE;
00308               incl_sym < symend;
00309               incl_sym += STABSIZE)
00310            {
00311              int incl_type;
00312 
00313              incl_type = incl_sym[TYPEOFF];
00314              if (incl_type == 0)
00315               break;
00316              else if (incl_type == (int) N_EXCL)
00317               continue;
00318              else if (incl_type == (int) N_EINCL)
00319               {
00320                 if (nest == 0)
00321                   break;
00322                 --nest;
00323               }
00324              else if (incl_type == (int) N_BINCL)
00325               ++nest;
00326              else if (nest == 0)
00327               {
00328                 const char *str;
00329 
00330                 str = ((char *) stabstrbuf
00331                       + stroff
00332                       + bfd_get_32 (abfd, incl_sym + STRDXOFF));
00333                 for (; *str != '\0'; str++)
00334                   {
00335                     if (num_chars >= buf_len)
00336                      {
00337                        buf_len += 32 * 1024;
00338                        symb = bfd_realloc (symb, buf_len);
00339                        if (symb == NULL)
00340                          goto error_return;
00341                        symb_rover = symb + num_chars;
00342                      }
00343                     * symb_rover ++ = * str;
00344                     sum_chars += *str;
00345                     num_chars ++;
00346                     if (*str == '(')
00347                      {
00348                        /* Skip the file number.  */
00349                        ++str;
00350                        while (ISDIGIT (*str))
00351                          ++str;
00352                        --str;
00353                      }
00354                   }
00355               }
00356            }
00357 
00358          BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
00359 
00360          /* If we have already included a header file with the same
00361             value, then replaced this one with an N_EXCL symbol.  */
00362          incl_entry = (struct stab_link_includes_entry * )
00363            bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
00364          if (incl_entry == NULL)
00365            goto error_return;
00366 
00367          for (t = incl_entry->totals; t != NULL; t = t->next)
00368            if (t->sum_chars == sum_chars
00369               && t->num_chars == num_chars
00370               && memcmp (t->symb, symb, num_chars) == 0)
00371              break;
00372 
00373          /* Record this symbol, so that we can set the value
00374             correctly.  */
00375          amt = sizeof *ne;
00376          ne = bfd_alloc (abfd, amt);
00377          if (ne == NULL)
00378            goto error_return;
00379          ne->offset = sym - stabbuf;
00380          ne->val = sum_chars;
00381          ne->type = (int) N_BINCL;
00382          ne->next = secinfo->excls;
00383          secinfo->excls = ne;
00384 
00385          if (t == NULL)
00386            {
00387              /* This is the first time we have seen this header file
00388                with this set of stabs strings.  */
00389              t = bfd_hash_allocate (&sinfo->includes, sizeof *t);
00390              if (t == NULL)
00391               goto error_return;
00392              t->sum_chars = sum_chars;
00393              t->num_chars = num_chars;
00394              t->symb = bfd_realloc (symb, num_chars); /* Trim data down.  */
00395              t->next = incl_entry->totals;
00396              incl_entry->totals = t;
00397            }
00398          else
00399            {
00400              bfd_size_type *incl_pstridx;
00401 
00402              /* We have seen this header file before.  Tell the final
00403                pass to change the type to N_EXCL.  */
00404              ne->type = (int) N_EXCL;
00405 
00406              /* Free off superfluous symbols.  */
00407              free (symb);
00408 
00409              /* Mark the skipped symbols.  */
00410 
00411              nest = 0;
00412              for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
00413                  incl_sym < symend;
00414                  incl_sym += STABSIZE, ++incl_pstridx)
00415               {
00416                 int incl_type;
00417 
00418                 incl_type = incl_sym[TYPEOFF];
00419 
00420                 if (incl_type == (int) N_EINCL)
00421                   {
00422                     if (nest == 0)
00423                      {
00424                        *incl_pstridx = (bfd_size_type) -1;
00425                        ++skip;
00426                        break;
00427                      }
00428                     --nest;
00429                   }
00430                 else if (incl_type == (int) N_BINCL)
00431                   ++nest;
00432                 else if (incl_type == (int) N_EXCL)
00433                   /* Keep existing exclusion marks.  */
00434                   continue;
00435                 else if (nest == 0)
00436                   {
00437                     *incl_pstridx = (bfd_size_type) -1;
00438                     ++skip;
00439                   }
00440               }
00441            }
00442        }
00443     }
00444 
00445   free (stabbuf);
00446   stabbuf = NULL;
00447   free (stabstrbuf);
00448   stabstrbuf = NULL;
00449 
00450   /* We need to set the section sizes such that the linker will
00451      compute the output section sizes correctly.  We set the .stab
00452      size to not include the entries we don't want.  We set
00453      SEC_EXCLUDE for the .stabstr section, so that it will be dropped
00454      from the link.  We record the size of the strtab in the first
00455      .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
00456      for that section.  */
00457   stabsec->size = (count - skip) * STABSIZE;
00458   if (stabsec->size == 0)
00459     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
00460   stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
00461   sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
00462 
00463   /* Calculate the `cumulative_skips' array now that stabs have been
00464      deleted for this section.  */
00465 
00466   if (skip != 0)
00467     {
00468       bfd_size_type i, offset;
00469       bfd_size_type *pskips;
00470 
00471       amt = count * sizeof (bfd_size_type);
00472       secinfo->cumulative_skips = bfd_alloc (abfd, amt);
00473       if (secinfo->cumulative_skips == NULL)
00474        goto error_return;
00475 
00476       pskips = secinfo->cumulative_skips;
00477       pstridx = secinfo->stridxs;
00478       offset = 0;
00479 
00480       for (i = 0; i < count; i++, pskips++, pstridx++)
00481        {
00482          *pskips = offset;
00483          if (*pstridx == (bfd_size_type) -1)
00484            offset += STABSIZE;
00485        }
00486 
00487       BFD_ASSERT (offset != 0);
00488     }
00489 
00490   return TRUE;
00491 
00492  error_return:
00493   if (stabbuf != NULL)
00494     free (stabbuf);
00495   if (stabstrbuf != NULL)
00496     free (stabstrbuf);
00497   return FALSE;
00498 }
00499 
00500 /* This function is called for each input file before the stab
00501    section is relocated.  It discards stab entries for discarded
00502    functions and variables.  The function returns TRUE iff
00503    any entries have been deleted.
00504 */
00505 
00506 bfd_boolean
00507 _bfd_discard_section_stabs (bfd *abfd,
00508                          asection *stabsec,
00509                          void * psecinfo,
00510                          bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
00511                          void * cookie)
00512 {
00513   bfd_size_type count, amt;
00514   struct stab_section_info *secinfo;
00515   bfd_byte *stabbuf = NULL;
00516   bfd_byte *sym, *symend;
00517   bfd_size_type skip;
00518   bfd_size_type *pstridx;
00519   int deleting;
00520 
00521   if (stabsec->size == 0)
00522     /* This file does not contain stabs debugging information.  */
00523     return FALSE;
00524 
00525   if (stabsec->size % STABSIZE != 0)
00526     /* Something is wrong with the format of these stab symbols.
00527        Don't try to optimize them.  */
00528     return FALSE;
00529 
00530   if ((stabsec->output_section != NULL
00531        && bfd_is_abs_section (stabsec->output_section)))
00532     /* At least one of the sections is being discarded from the
00533        link, so we should just ignore them.  */
00534     return FALSE;
00535 
00536   /* We should have initialized our data in _bfd_link_stab_sections.
00537      If there was some bizarre error reading the string sections, though,
00538      we might not have.  Bail rather than asserting.  */
00539   if (psecinfo == NULL)
00540     return FALSE;
00541 
00542   count = stabsec->rawsize / STABSIZE;
00543   secinfo = (struct stab_section_info *) psecinfo;
00544 
00545   /* Read the stabs information from abfd.  */
00546   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
00547     goto error_return;
00548 
00549   /* Look through the stabs symbols and discard any information for
00550      discarded functions.  */
00551   skip = 0;
00552   deleting = -1;
00553 
00554   symend = stabbuf + stabsec->rawsize;
00555   for (sym = stabbuf, pstridx = secinfo->stridxs;
00556        sym < symend;
00557        sym += STABSIZE, ++pstridx)
00558     {
00559       int type;
00560 
00561       if (*pstridx == (bfd_size_type) -1)
00562        /* This stab was deleted in a previous pass.  */
00563        continue;
00564 
00565       type = sym[TYPEOFF];
00566 
00567       if (type == (int) N_FUN)
00568        {
00569          int strx = bfd_get_32 (abfd, sym + STRDXOFF);
00570 
00571          if (strx == 0)
00572            {
00573              if (deleting)
00574               {
00575                 skip++;
00576                 *pstridx = -1;
00577               }
00578              deleting = -1;
00579              continue;
00580            }
00581          deleting = 0;
00582          if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
00583            deleting = 1;
00584        }
00585 
00586       if (deleting == 1)
00587        {
00588          *pstridx = -1;
00589          skip++;
00590        }
00591       else if (deleting == -1)
00592        {
00593          /* Outside of a function.  Check for deleted variables.  */
00594          if (type == (int) N_STSYM || type == (int) N_LCSYM)
00595            if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
00596              {
00597               *pstridx = -1;
00598               skip ++;
00599              }
00600          /* We should also check for N_GSYM entries which reference a
00601             deleted global, but those are less harmful to debuggers
00602             and would require parsing the stab strings.  */
00603        }
00604     }
00605 
00606   free (stabbuf);
00607   stabbuf = NULL;
00608 
00609   /* Shrink the stabsec as needed.  */
00610   stabsec->size -= skip * STABSIZE;
00611   if (stabsec->size == 0)
00612     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
00613 
00614   /* Recalculate the `cumulative_skips' array now that stabs have been
00615      deleted for this section.  */
00616 
00617   if (skip != 0)
00618     {
00619       bfd_size_type i, offset;
00620       bfd_size_type *pskips;
00621 
00622       if (secinfo->cumulative_skips == NULL)
00623        {
00624          amt = count * sizeof (bfd_size_type);
00625          secinfo->cumulative_skips = bfd_alloc (abfd, amt);
00626          if (secinfo->cumulative_skips == NULL)
00627            goto error_return;
00628        }
00629 
00630       pskips = secinfo->cumulative_skips;
00631       pstridx = secinfo->stridxs;
00632       offset = 0;
00633 
00634       for (i = 0; i < count; i++, pskips++, pstridx++)
00635        {
00636          *pskips = offset;
00637          if (*pstridx == (bfd_size_type) -1)
00638            offset += STABSIZE;
00639        }
00640 
00641       BFD_ASSERT (offset != 0);
00642     }
00643 
00644   return skip > 0;
00645 
00646  error_return:
00647   if (stabbuf != NULL)
00648     free (stabbuf);
00649   return FALSE;
00650 }
00651 
00652 /* Write out the stab section.  This is called with the relocated
00653    contents.  */
00654 
00655 bfd_boolean
00656 _bfd_write_section_stabs (bfd *output_bfd,
00657                        struct stab_info *sinfo,
00658                        asection *stabsec,
00659                        void * *psecinfo,
00660                        bfd_byte *contents)
00661 {
00662   struct stab_section_info *secinfo;
00663   struct stab_excl_list *e;
00664   bfd_byte *sym, *tosym, *symend;
00665   bfd_size_type *pstridx;
00666 
00667   secinfo = (struct stab_section_info *) *psecinfo;
00668 
00669   if (secinfo == NULL)
00670     return bfd_set_section_contents (output_bfd, stabsec->output_section,
00671                                  contents, stabsec->output_offset,
00672                                  stabsec->size);
00673 
00674   /* Handle each N_BINCL entry.  */
00675   for (e = secinfo->excls; e != NULL; e = e->next)
00676     {
00677       bfd_byte *excl_sym;
00678 
00679       BFD_ASSERT (e->offset < stabsec->rawsize);
00680       excl_sym = contents + e->offset;
00681       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
00682       excl_sym[TYPEOFF] = e->type;
00683     }
00684 
00685   /* Copy over all the stabs symbols, omitting the ones we don't want,
00686      and correcting the string indices for those we do want.  */
00687   tosym = contents;
00688   symend = contents + stabsec->rawsize;
00689   for (sym = contents, pstridx = secinfo->stridxs;
00690        sym < symend;
00691        sym += STABSIZE, ++pstridx)
00692     {
00693       if (*pstridx != (bfd_size_type) -1)
00694        {
00695          if (tosym != sym)
00696            memcpy (tosym, sym, STABSIZE);
00697          bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
00698 
00699          if (sym[TYPEOFF] == 0)
00700            {
00701              /* This is the header symbol for the stabs section.  We
00702                don't really need one, since we have merged all the
00703                input stabs sections into one, but we generate one
00704                for the benefit of readers which expect to see one.  */
00705              BFD_ASSERT (sym == contents);
00706              bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
00707                        tosym + VALOFF);
00708              bfd_put_16 (output_bfd,
00709                        stabsec->output_section->size / STABSIZE - 1,
00710                        tosym + DESCOFF);
00711            }
00712 
00713          tosym += STABSIZE;
00714        }
00715     }
00716 
00717   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
00718 
00719   return bfd_set_section_contents (output_bfd, stabsec->output_section,
00720                                contents, (file_ptr) stabsec->output_offset,
00721                                stabsec->size);
00722 }
00723 
00724 /* Write out the .stabstr section.  */
00725 
00726 bfd_boolean
00727 _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
00728 {
00729   if (bfd_is_abs_section (sinfo->stabstr->output_section))
00730     /* The section was discarded from the link.  */
00731     return TRUE;
00732 
00733   BFD_ASSERT ((sinfo->stabstr->output_offset
00734               + _bfd_stringtab_size (sinfo->strings))
00735              <= sinfo->stabstr->output_section->size);
00736 
00737   if (bfd_seek (output_bfd,
00738               (file_ptr) (sinfo->stabstr->output_section->filepos
00739                          + sinfo->stabstr->output_offset),
00740               SEEK_SET) != 0)
00741     return FALSE;
00742 
00743   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
00744     return FALSE;
00745 
00746   /* We no longer need the stabs information.  */
00747   _bfd_stringtab_free (sinfo->strings);
00748   bfd_hash_table_free (&sinfo->includes);
00749 
00750   return TRUE;
00751 }
00752 
00753 /* Adjust an address in the .stab section.  Given OFFSET within
00754    STABSEC, this returns the new offset in the adjusted stab section,
00755    or -1 if the address refers to a stab which has been removed.  */
00756 
00757 bfd_vma
00758 _bfd_stab_section_offset (asection *stabsec,
00759                        void * psecinfo,
00760                        bfd_vma offset)
00761 {
00762   struct stab_section_info *secinfo;
00763 
00764   secinfo = (struct stab_section_info *) psecinfo;
00765 
00766   if (secinfo == NULL)
00767     return offset;
00768 
00769   if (offset >= stabsec->rawsize)
00770     return offset - stabsec->rawsize + stabsec->size;
00771 
00772   if (secinfo->cumulative_skips)
00773     {
00774       bfd_vma i;
00775 
00776       i = offset / STABSIZE;
00777 
00778       if (secinfo->stridxs [i] == (bfd_size_type) -1)
00779        return (bfd_vma) -1;
00780 
00781       return offset - secinfo->cumulative_skips [i];
00782     }
00783 
00784   return offset;
00785 }