Home | History | Annotate | Line # | Download | only in bfd
stabs.c revision 1.1.1.1
      1 /* Stabs in sections linking support.
      2    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
      3    2006, 2007 Free Software Foundation, Inc.
      4    Written by Ian Lance Taylor, Cygnus Support.
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 
     24 /* This file contains support for linking stabs in sections, as used
     25    on COFF and ELF.  */
     26 
     27 #include "sysdep.h"
     28 #include "bfd.h"
     29 #include "libbfd.h"
     30 #include "aout/stab_gnu.h"
     31 #include "safe-ctype.h"
     32 
     33 /* Stabs entries use a 12 byte format:
     34      4 byte string table index
     35      1 byte stab type
     36      1 byte stab other field
     37      2 byte stab desc field
     38      4 byte stab value
     39    FIXME: This will have to change for a 64 bit object format.
     40 
     41    The stabs symbols are divided into compilation units.  For the
     42    first entry in each unit, the type of 0, the value is the length of
     43    the string table for this unit, and the desc field is the number of
     44    stabs symbols for this unit.  */
     45 
     46 #define STRDXOFF  0
     47 #define TYPEOFF   4
     48 #define OTHEROFF  5
     49 #define DESCOFF   6
     50 #define VALOFF    8
     51 #define STABSIZE  12
     52 
     53 /* A linked list of totals that we have found for a particular header
     54    file.  A total is a unique identifier for a particular BINCL...EINCL
     55    sequence of STABs that can be used to identify duplicate sequences.
     56    It consists of three fields, 'sum_chars' which is the sum of all the
     57    STABS characters; 'num_chars' which is the number of these charactes
     58    and 'symb' which is a buffer of all the symbols in the sequence.  This
     59    buffer is only checked as a last resort.  */
     60 
     61 struct stab_link_includes_totals
     62 {
     63   struct stab_link_includes_totals *next;
     64   bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
     65   bfd_vma num_chars;  /* Number of STABS characters.  */
     66   const char* symb;   /* The STABS characters themselves.  */
     67 };
     68 
     69 /* An entry in the header file hash table.  */
     70 
     71 struct stab_link_includes_entry
     72 {
     73   struct bfd_hash_entry root;
     74   /* List of totals we have found for this file.  */
     75   struct stab_link_includes_totals *totals;
     76 };
     77 
     78 /* This structure is used to hold a list of N_BINCL symbols, some of
     79    which might be converted into N_EXCL symbols.  */
     80 
     81 struct stab_excl_list
     82 {
     83   /* The next symbol to convert.  */
     84   struct stab_excl_list *next;
     85   /* The offset to this symbol in the section contents.  */
     86   bfd_size_type offset;
     87   /* The value to use for the symbol.  */
     88   bfd_vma val;
     89   /* The type of this symbol (N_BINCL or N_EXCL).  */
     90   int type;
     91 };
     92 
     93 /* This structure is stored with each .stab section.  */
     94 
     95 struct stab_section_info
     96 {
     97   /* This is a linked list of N_BINCL symbols which should be
     98      converted into N_EXCL symbols.  */
     99   struct stab_excl_list *excls;
    100 
    101   /* This is used to map input stab offsets within their sections
    102      to output stab offsets, to take into account stabs that have
    103      been deleted.  If it is NULL, the output offsets are the same
    104      as the input offsets, because no stabs have been deleted from
    105      this section.  Otherwise the i'th entry is the number of
    106      bytes of stabs that have been deleted prior to the i'th
    107      stab.  */
    108   bfd_size_type *cumulative_skips;
    109 
    110   /* This is an array of string indices.  For each stab symbol, we
    111      store the string index here.  If a stab symbol should not be
    112      included in the final output, the string index is -1.  */
    113   bfd_size_type stridxs[1];
    114 };
    115 
    116 
    117 /* The function to create a new entry in the header file hash table.  */
    119 
    120 static struct bfd_hash_entry *
    121 stab_link_includes_newfunc (struct bfd_hash_entry *entry,
    122 			    struct bfd_hash_table *table,
    123 			    const char *string)
    124 {
    125   struct stab_link_includes_entry *ret =
    126     (struct stab_link_includes_entry *) entry;
    127 
    128   /* Allocate the structure if it has not already been allocated by a
    129      subclass.  */
    130   if (ret == NULL)
    131     ret = bfd_hash_allocate (table,
    132 			     sizeof (struct stab_link_includes_entry));
    133   if (ret == NULL)
    134     return NULL;
    135 
    136   /* Call the allocation method of the superclass.  */
    137   ret = ((struct stab_link_includes_entry *)
    138 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
    139   if (ret)
    140     /* Set local fields.  */
    141     ret->totals = NULL;
    142 
    143   return (struct bfd_hash_entry *) ret;
    144 }
    145 
    146 /* This function is called for each input file from the add_symbols
    148    pass of the linker.  */
    149 
    150 bfd_boolean
    151 _bfd_link_section_stabs (bfd *abfd,
    152 			 struct stab_info *sinfo,
    153 			 asection *stabsec,
    154 			 asection *stabstrsec,
    155 			 void * *psecinfo,
    156 			 bfd_size_type *pstring_offset)
    157 {
    158   bfd_boolean first;
    159   bfd_size_type count, amt;
    160   struct stab_section_info *secinfo;
    161   bfd_byte *stabbuf = NULL;
    162   bfd_byte *stabstrbuf = NULL;
    163   bfd_byte *sym, *symend;
    164   bfd_size_type stroff, next_stroff, skip;
    165   bfd_size_type *pstridx;
    166 
    167   if (stabsec->size == 0
    168       || stabstrsec->size == 0)
    169     /* This file does not contain stabs debugging information.  */
    170     return TRUE;
    171 
    172   if (stabsec->size % STABSIZE != 0)
    173     /* Something is wrong with the format of these stab symbols.
    174        Don't try to optimize them.  */
    175     return TRUE;
    176 
    177   if ((stabstrsec->flags & SEC_RELOC) != 0)
    178     /* We shouldn't see relocations in the strings, and we aren't
    179        prepared to handle them.  */
    180     return TRUE;
    181 
    182   if (bfd_is_abs_section (stabsec->output_section)
    183       || bfd_is_abs_section (stabstrsec->output_section))
    184     /* At least one of the sections is being discarded from the
    185        link, so we should just ignore them.  */
    186     return TRUE;
    187 
    188   first = FALSE;
    189 
    190   if (sinfo->stabstr == NULL)
    191     {
    192       flagword flags;
    193 
    194       /* Initialize the stabs information we need to keep track of.  */
    195       first = TRUE;
    196       sinfo->strings = _bfd_stringtab_init ();
    197       if (sinfo->strings == NULL)
    198 	goto error_return;
    199       /* Make sure the first byte is zero.  */
    200       (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
    201       if (! bfd_hash_table_init (&sinfo->includes,
    202 				 stab_link_includes_newfunc,
    203 				 sizeof (struct stab_link_includes_entry)))
    204 	goto error_return;
    205       flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
    206 	       | SEC_LINKER_CREATED);
    207       sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
    208 							   flags);
    209       if (sinfo->stabstr == NULL)
    210 	goto error_return;
    211     }
    212 
    213   /* Initialize the information we are going to store for this .stab
    214      section.  */
    215   count = stabsec->size / STABSIZE;
    216 
    217   amt = sizeof (struct stab_section_info);
    218   amt += (count - 1) * sizeof (bfd_size_type);
    219   *psecinfo = bfd_alloc (abfd, amt);
    220   if (*psecinfo == NULL)
    221     goto error_return;
    222 
    223   secinfo = (struct stab_section_info *) *psecinfo;
    224   secinfo->excls = NULL;
    225   stabsec->rawsize = stabsec->size;
    226   secinfo->cumulative_skips = NULL;
    227   memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
    228 
    229   /* Read the stabs information from abfd.  */
    230   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
    231       || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
    232     goto error_return;
    233 
    234   /* Look through the stabs symbols, work out the new string indices,
    235      and identify N_BINCL symbols which can be eliminated.  */
    236   stroff = 0;
    237   /* The stabs sections can be split when
    238      -split-by-reloc/-split-by-file is used.  We must keep track of
    239      each stab section's place in the single concatenated string
    240      table.  */
    241   next_stroff = pstring_offset ? *pstring_offset : 0;
    242   skip = 0;
    243 
    244   symend = stabbuf + stabsec->size;
    245   for (sym = stabbuf, pstridx = secinfo->stridxs;
    246        sym < symend;
    247        sym += STABSIZE, ++pstridx)
    248     {
    249       bfd_size_type symstroff;
    250       int type;
    251       const char *string;
    252 
    253       if (*pstridx != 0)
    254 	/* This symbol has already been handled by an N_BINCL pass.  */
    255 	continue;
    256 
    257       type = sym[TYPEOFF];
    258 
    259       if (type == 0)
    260 	{
    261 	  /* Special type 0 stabs indicate the offset to the next
    262 	     string table.  We only copy the very first one.  */
    263 	  stroff = next_stroff;
    264 	  next_stroff += bfd_get_32 (abfd, sym + 8);
    265 	  if (pstring_offset)
    266 	    *pstring_offset = next_stroff;
    267 	  if (! first)
    268 	    {
    269 	      *pstridx = (bfd_size_type) -1;
    270 	      ++skip;
    271 	      continue;
    272 	    }
    273 	  first = FALSE;
    274 	}
    275 
    276       /* Store the string in the hash table, and record the index.  */
    277       symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
    278       if (symstroff >= stabstrsec->size)
    279 	{
    280 	  (*_bfd_error_handler)
    281 	    (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
    282 	     abfd, stabsec, (long) (sym - stabbuf));
    283 	  bfd_set_error (bfd_error_bad_value);
    284 	  goto error_return;
    285 	}
    286       string = (char *) stabstrbuf + symstroff;
    287       *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
    288 
    289       /* An N_BINCL symbol indicates the start of the stabs entries
    290 	 for a header file.  We need to scan ahead to the next N_EINCL
    291 	 symbol, ignoring nesting, adding up all the characters in the
    292 	 symbol names, not including the file numbers in types (the
    293 	 first number after an open parenthesis).  */
    294       if (type == (int) N_BINCL)
    295 	{
    296 	  bfd_vma sum_chars;
    297 	  bfd_vma num_chars;
    298 	  bfd_vma buf_len = 0;
    299 	  char * symb;
    300 	  char * symb_rover;
    301 	  int nest;
    302 	  bfd_byte * incl_sym;
    303 	  struct stab_link_includes_entry * incl_entry;
    304 	  struct stab_link_includes_totals * t;
    305 	  struct stab_excl_list * ne;
    306 
    307 	  symb = symb_rover = NULL;
    308 	  sum_chars = num_chars = 0;
    309 	  nest = 0;
    310 
    311 	  for (incl_sym = sym + STABSIZE;
    312 	       incl_sym < symend;
    313 	       incl_sym += STABSIZE)
    314 	    {
    315 	      int incl_type;
    316 
    317 	      incl_type = incl_sym[TYPEOFF];
    318 	      if (incl_type == 0)
    319 		break;
    320 	      else if (incl_type == (int) N_EXCL)
    321 		continue;
    322 	      else if (incl_type == (int) N_EINCL)
    323 		{
    324 		  if (nest == 0)
    325 		    break;
    326 		  --nest;
    327 		}
    328 	      else if (incl_type == (int) N_BINCL)
    329 		++nest;
    330 	      else if (nest == 0)
    331 		{
    332 		  const char *str;
    333 
    334 		  str = ((char *) stabstrbuf
    335 			 + stroff
    336 			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
    337 		  for (; *str != '\0'; str++)
    338 		    {
    339 		      if (num_chars >= buf_len)
    340 			{
    341 			  buf_len += 32 * 1024;
    342 			  symb = bfd_realloc_or_free (symb, buf_len);
    343 			  if (symb == NULL)
    344 			    goto error_return;
    345 			  symb_rover = symb + num_chars;
    346 			}
    347 		      * symb_rover ++ = * str;
    348 		      sum_chars += *str;
    349 		      num_chars ++;
    350 		      if (*str == '(')
    351 			{
    352 			  /* Skip the file number.  */
    353 			  ++str;
    354 			  while (ISDIGIT (*str))
    355 			    ++str;
    356 			  --str;
    357 			}
    358 		    }
    359 		}
    360 	    }
    361 
    362 	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
    363 
    364 	  /* If we have already included a header file with the same
    365 	     value, then replaced this one with an N_EXCL symbol.  */
    366 	  incl_entry = (struct stab_link_includes_entry * )
    367 	    bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
    368 	  if (incl_entry == NULL)
    369 	    goto error_return;
    370 
    371 	  for (t = incl_entry->totals; t != NULL; t = t->next)
    372 	    if (t->sum_chars == sum_chars
    373 		&& t->num_chars == num_chars
    374 		&& memcmp (t->symb, symb, num_chars) == 0)
    375 	      break;
    376 
    377 	  /* Record this symbol, so that we can set the value
    378 	     correctly.  */
    379 	  amt = sizeof *ne;
    380 	  ne = bfd_alloc (abfd, amt);
    381 	  if (ne == NULL)
    382 	    goto error_return;
    383 	  ne->offset = sym - stabbuf;
    384 	  ne->val = sum_chars;
    385 	  ne->type = (int) N_BINCL;
    386 	  ne->next = secinfo->excls;
    387 	  secinfo->excls = ne;
    388 
    389 	  if (t == NULL)
    390 	    {
    391 	      /* This is the first time we have seen this header file
    392 		 with this set of stabs strings.  */
    393 	      t = bfd_hash_allocate (&sinfo->includes, sizeof *t);
    394 	      if (t == NULL)
    395 		goto error_return;
    396 	      t->sum_chars = sum_chars;
    397 	      t->num_chars = num_chars;
    398 	      t->symb = symb = bfd_realloc_or_free (symb, num_chars); /* Trim data down.  */
    399 	      t->next = incl_entry->totals;
    400 	      incl_entry->totals = t;
    401 	    }
    402 	  else
    403 	    {
    404 	      bfd_size_type *incl_pstridx;
    405 
    406 	      /* We have seen this header file before.  Tell the final
    407 		 pass to change the type to N_EXCL.  */
    408 	      ne->type = (int) N_EXCL;
    409 
    410 	      /* Free off superfluous symbols.  */
    411 	      free (symb);
    412 
    413 	      /* Mark the skipped symbols.  */
    414 
    415 	      nest = 0;
    416 	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
    417 		   incl_sym < symend;
    418 		   incl_sym += STABSIZE, ++incl_pstridx)
    419 		{
    420 		  int incl_type;
    421 
    422 		  incl_type = incl_sym[TYPEOFF];
    423 
    424 		  if (incl_type == (int) N_EINCL)
    425 		    {
    426 		      if (nest == 0)
    427 			{
    428 			  *incl_pstridx = (bfd_size_type) -1;
    429 			  ++skip;
    430 			  break;
    431 			}
    432 		      --nest;
    433 		    }
    434 		  else if (incl_type == (int) N_BINCL)
    435 		    ++nest;
    436 		  else if (incl_type == (int) N_EXCL)
    437 		    /* Keep existing exclusion marks.  */
    438 		    continue;
    439 		  else if (nest == 0)
    440 		    {
    441 		      *incl_pstridx = (bfd_size_type) -1;
    442 		      ++skip;
    443 		    }
    444 		}
    445 	    }
    446 	}
    447     }
    448 
    449   free (stabbuf);
    450   stabbuf = NULL;
    451   free (stabstrbuf);
    452   stabstrbuf = NULL;
    453 
    454   /* We need to set the section sizes such that the linker will
    455      compute the output section sizes correctly.  We set the .stab
    456      size to not include the entries we don't want.  We set
    457      SEC_EXCLUDE for the .stabstr section, so that it will be dropped
    458      from the link.  We record the size of the strtab in the first
    459      .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
    460      for that section.  */
    461   stabsec->size = (count - skip) * STABSIZE;
    462   if (stabsec->size == 0)
    463     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    464   stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    465   sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
    466 
    467   /* Calculate the `cumulative_skips' array now that stabs have been
    468      deleted for this section.  */
    469 
    470   if (skip != 0)
    471     {
    472       bfd_size_type i, offset;
    473       bfd_size_type *pskips;
    474 
    475       amt = count * sizeof (bfd_size_type);
    476       secinfo->cumulative_skips = bfd_alloc (abfd, amt);
    477       if (secinfo->cumulative_skips == NULL)
    478 	goto error_return;
    479 
    480       pskips = secinfo->cumulative_skips;
    481       pstridx = secinfo->stridxs;
    482       offset = 0;
    483 
    484       for (i = 0; i < count; i++, pskips++, pstridx++)
    485 	{
    486 	  *pskips = offset;
    487 	  if (*pstridx == (bfd_size_type) -1)
    488 	    offset += STABSIZE;
    489 	}
    490 
    491       BFD_ASSERT (offset != 0);
    492     }
    493 
    494   return TRUE;
    495 
    496  error_return:
    497   if (stabbuf != NULL)
    498     free (stabbuf);
    499   if (stabstrbuf != NULL)
    500     free (stabstrbuf);
    501   return FALSE;
    502 }
    503 
    504 /* This function is called for each input file before the stab
    506    section is relocated.  It discards stab entries for discarded
    507    functions and variables.  The function returns TRUE iff
    508    any entries have been deleted.
    509 */
    510 
    511 bfd_boolean
    512 _bfd_discard_section_stabs (bfd *abfd,
    513 			    asection *stabsec,
    514 			    void * psecinfo,
    515 			    bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
    516 			    void * cookie)
    517 {
    518   bfd_size_type count, amt;
    519   struct stab_section_info *secinfo;
    520   bfd_byte *stabbuf = NULL;
    521   bfd_byte *sym, *symend;
    522   bfd_size_type skip;
    523   bfd_size_type *pstridx;
    524   int deleting;
    525 
    526   if (stabsec->size == 0)
    527     /* This file does not contain stabs debugging information.  */
    528     return FALSE;
    529 
    530   if (stabsec->size % STABSIZE != 0)
    531     /* Something is wrong with the format of these stab symbols.
    532        Don't try to optimize them.  */
    533     return FALSE;
    534 
    535   if ((stabsec->output_section != NULL
    536        && bfd_is_abs_section (stabsec->output_section)))
    537     /* At least one of the sections is being discarded from the
    538        link, so we should just ignore them.  */
    539     return FALSE;
    540 
    541   /* We should have initialized our data in _bfd_link_stab_sections.
    542      If there was some bizarre error reading the string sections, though,
    543      we might not have.  Bail rather than asserting.  */
    544   if (psecinfo == NULL)
    545     return FALSE;
    546 
    547   count = stabsec->rawsize / STABSIZE;
    548   secinfo = (struct stab_section_info *) psecinfo;
    549 
    550   /* Read the stabs information from abfd.  */
    551   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
    552     goto error_return;
    553 
    554   /* Look through the stabs symbols and discard any information for
    555      discarded functions.  */
    556   skip = 0;
    557   deleting = -1;
    558 
    559   symend = stabbuf + stabsec->rawsize;
    560   for (sym = stabbuf, pstridx = secinfo->stridxs;
    561        sym < symend;
    562        sym += STABSIZE, ++pstridx)
    563     {
    564       int type;
    565 
    566       if (*pstridx == (bfd_size_type) -1)
    567 	/* This stab was deleted in a previous pass.  */
    568 	continue;
    569 
    570       type = sym[TYPEOFF];
    571 
    572       if (type == (int) N_FUN)
    573 	{
    574 	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
    575 
    576 	  if (strx == 0)
    577 	    {
    578 	      if (deleting)
    579 		{
    580 		  skip++;
    581 		  *pstridx = -1;
    582 		}
    583 	      deleting = -1;
    584 	      continue;
    585 	    }
    586 	  deleting = 0;
    587 	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
    588 	    deleting = 1;
    589 	}
    590 
    591       if (deleting == 1)
    592 	{
    593 	  *pstridx = -1;
    594 	  skip++;
    595 	}
    596       else if (deleting == -1)
    597 	{
    598 	  /* Outside of a function.  Check for deleted variables.  */
    599 	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
    600 	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
    601 	      {
    602 		*pstridx = -1;
    603 		skip ++;
    604 	      }
    605 	  /* We should also check for N_GSYM entries which reference a
    606 	     deleted global, but those are less harmful to debuggers
    607 	     and would require parsing the stab strings.  */
    608 	}
    609     }
    610 
    611   free (stabbuf);
    612   stabbuf = NULL;
    613 
    614   /* Shrink the stabsec as needed.  */
    615   stabsec->size -= skip * STABSIZE;
    616   if (stabsec->size == 0)
    617     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    618 
    619   /* Recalculate the `cumulative_skips' array now that stabs have been
    620      deleted for this section.  */
    621 
    622   if (skip != 0)
    623     {
    624       bfd_size_type i, offset;
    625       bfd_size_type *pskips;
    626 
    627       if (secinfo->cumulative_skips == NULL)
    628 	{
    629 	  amt = count * sizeof (bfd_size_type);
    630 	  secinfo->cumulative_skips = bfd_alloc (abfd, amt);
    631 	  if (secinfo->cumulative_skips == NULL)
    632 	    goto error_return;
    633 	}
    634 
    635       pskips = secinfo->cumulative_skips;
    636       pstridx = secinfo->stridxs;
    637       offset = 0;
    638 
    639       for (i = 0; i < count; i++, pskips++, pstridx++)
    640 	{
    641 	  *pskips = offset;
    642 	  if (*pstridx == (bfd_size_type) -1)
    643 	    offset += STABSIZE;
    644 	}
    645 
    646       BFD_ASSERT (offset != 0);
    647     }
    648 
    649   return skip > 0;
    650 
    651  error_return:
    652   if (stabbuf != NULL)
    653     free (stabbuf);
    654   return FALSE;
    655 }
    656 
    657 /* Write out the stab section.  This is called with the relocated
    658    contents.  */
    659 
    660 bfd_boolean
    661 _bfd_write_section_stabs (bfd *output_bfd,
    662 			  struct stab_info *sinfo,
    663 			  asection *stabsec,
    664 			  void * *psecinfo,
    665 			  bfd_byte *contents)
    666 {
    667   struct stab_section_info *secinfo;
    668   struct stab_excl_list *e;
    669   bfd_byte *sym, *tosym, *symend;
    670   bfd_size_type *pstridx;
    671 
    672   secinfo = (struct stab_section_info *) *psecinfo;
    673 
    674   if (secinfo == NULL)
    675     return bfd_set_section_contents (output_bfd, stabsec->output_section,
    676 				     contents, stabsec->output_offset,
    677 				     stabsec->size);
    678 
    679   /* Handle each N_BINCL entry.  */
    680   for (e = secinfo->excls; e != NULL; e = e->next)
    681     {
    682       bfd_byte *excl_sym;
    683 
    684       BFD_ASSERT (e->offset < stabsec->rawsize);
    685       excl_sym = contents + e->offset;
    686       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
    687       excl_sym[TYPEOFF] = e->type;
    688     }
    689 
    690   /* Copy over all the stabs symbols, omitting the ones we don't want,
    691      and correcting the string indices for those we do want.  */
    692   tosym = contents;
    693   symend = contents + stabsec->rawsize;
    694   for (sym = contents, pstridx = secinfo->stridxs;
    695        sym < symend;
    696        sym += STABSIZE, ++pstridx)
    697     {
    698       if (*pstridx != (bfd_size_type) -1)
    699 	{
    700 	  if (tosym != sym)
    701 	    memcpy (tosym, sym, STABSIZE);
    702 	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
    703 
    704 	  if (sym[TYPEOFF] == 0)
    705 	    {
    706 	      /* This is the header symbol for the stabs section.  We
    707 		 don't really need one, since we have merged all the
    708 		 input stabs sections into one, but we generate one
    709 		 for the benefit of readers which expect to see one.  */
    710 	      BFD_ASSERT (sym == contents);
    711 	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
    712 			  tosym + VALOFF);
    713 	      bfd_put_16 (output_bfd,
    714 			  stabsec->output_section->size / STABSIZE - 1,
    715 			  tosym + DESCOFF);
    716 	    }
    717 
    718 	  tosym += STABSIZE;
    719 	}
    720     }
    721 
    722   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
    723 
    724   return bfd_set_section_contents (output_bfd, stabsec->output_section,
    725 				   contents, (file_ptr) stabsec->output_offset,
    726 				   stabsec->size);
    727 }
    728 
    729 /* Write out the .stabstr section.  */
    730 
    731 bfd_boolean
    732 _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
    733 {
    734   if (bfd_is_abs_section (sinfo->stabstr->output_section))
    735     /* The section was discarded from the link.  */
    736     return TRUE;
    737 
    738   BFD_ASSERT ((sinfo->stabstr->output_offset
    739 	       + _bfd_stringtab_size (sinfo->strings))
    740 	      <= sinfo->stabstr->output_section->size);
    741 
    742   if (bfd_seek (output_bfd,
    743 		(file_ptr) (sinfo->stabstr->output_section->filepos
    744 			    + sinfo->stabstr->output_offset),
    745 		SEEK_SET) != 0)
    746     return FALSE;
    747 
    748   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
    749     return FALSE;
    750 
    751   /* We no longer need the stabs information.  */
    752   _bfd_stringtab_free (sinfo->strings);
    753   bfd_hash_table_free (&sinfo->includes);
    754 
    755   return TRUE;
    756 }
    757 
    758 /* Adjust an address in the .stab section.  Given OFFSET within
    759    STABSEC, this returns the new offset in the adjusted stab section,
    760    or -1 if the address refers to a stab which has been removed.  */
    761 
    762 bfd_vma
    763 _bfd_stab_section_offset (asection *stabsec,
    764 			  void * psecinfo,
    765 			  bfd_vma offset)
    766 {
    767   struct stab_section_info *secinfo;
    768 
    769   secinfo = (struct stab_section_info *) psecinfo;
    770 
    771   if (secinfo == NULL)
    772     return offset;
    773 
    774   if (offset >= stabsec->rawsize)
    775     return offset - stabsec->rawsize + stabsec->size;
    776 
    777   if (secinfo->cumulative_skips)
    778     {
    779       bfd_vma i;
    780 
    781       i = offset / STABSIZE;
    782 
    783       if (secinfo->stridxs [i] == (bfd_size_type) -1)
    784 	return (bfd_vma) -1;
    785 
    786       return offset - secinfo->cumulative_skips [i];
    787     }
    788 
    789   return offset;
    790 }
    791