Home | History | Annotate | Line # | Download | only in bfd
stabs.c revision 1.8
      1 /* Stabs in sections linking support.
      2    Copyright (C) 1996-2022 Free Software Foundation, Inc.
      3    Written by Ian Lance Taylor, Cygnus Support.
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 
     23 /* This file contains support for linking stabs in sections, as used
     24    on COFF and ELF.  */
     25 
     26 #include "sysdep.h"
     27 #include "bfd.h"
     28 #include "libbfd.h"
     29 #include "aout/stab_gnu.h"
     30 #include "safe-ctype.h"
     31 
     32 /* Stabs entries use a 12 byte format:
     33      4 byte string table index
     34      1 byte stab type
     35      1 byte stab other field
     36      2 byte stab desc field
     37      4 byte stab value
     38    FIXME: This will have to change for a 64 bit object format.
     39 
     40    The stabs symbols are divided into compilation units.  For the
     41    first entry in each unit, the type of 0, the value is the length of
     42    the string table for this unit, and the desc field is the number of
     43    stabs symbols for this unit.  */
     44 
     45 #define STRDXOFF  0
     46 #define TYPEOFF   4
     47 #define OTHEROFF  5
     48 #define DESCOFF   6
     49 #define VALOFF    8
     50 #define STABSIZE  12
     51 
     52 /* A linked list of totals that we have found for a particular header
     53    file.  A total is a unique identifier for a particular BINCL...EINCL
     54    sequence of STABs that can be used to identify duplicate sequences.
     55    It consists of three fields, 'sum_chars' which is the sum of all the
     56    STABS characters; 'num_chars' which is the number of these charactes
     57    and 'symb' which is a buffer of all the symbols in the sequence.  This
     58    buffer is only checked as a last resort.  */
     59 
     60 struct stab_link_includes_totals
     61 {
     62   struct stab_link_includes_totals *next;
     63   bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
     64   bfd_vma num_chars;  /* Number of STABS characters.  */
     65   const char* symb;   /* The STABS characters themselves.  */
     66 };
     67 
     68 /* An entry in the header file hash table.  */
     69 
     70 struct stab_link_includes_entry
     71 {
     72   struct bfd_hash_entry root;
     73   /* List of totals we have found for this file.  */
     74   struct stab_link_includes_totals *totals;
     75 };
     76 
     77 /* This structure is used to hold a list of N_BINCL symbols, some of
     78    which might be converted into N_EXCL symbols.  */
     79 
     80 struct stab_excl_list
     81 {
     82   /* The next symbol to convert.  */
     83   struct stab_excl_list *next;
     84   /* The offset to this symbol in the section contents.  */
     85   bfd_size_type offset;
     86   /* The value to use for the symbol.  */
     87   bfd_vma val;
     88   /* The type of this symbol (N_BINCL or N_EXCL).  */
     89   int type;
     90 };
     91 
     92 /* This structure is stored with each .stab section.  */
     93 
     94 struct stab_section_info
     95 {
     96   /* This is a linked list of N_BINCL symbols which should be
     97      converted into N_EXCL symbols.  */
     98   struct stab_excl_list *excls;
     99 
    100   /* This is used to map input stab offsets within their sections
    101      to output stab offsets, to take into account stabs that have
    102      been deleted.  If it is NULL, the output offsets are the same
    103      as the input offsets, because no stabs have been deleted from
    104      this section.  Otherwise the i'th entry is the number of
    105      bytes of stabs that have been deleted prior to the i'th
    106      stab.  */
    107   bfd_size_type *cumulative_skips;
    108 
    109   /* This is an array of string indices.  For each stab symbol, we
    110      store the string index here.  If a stab symbol should not be
    111      included in the final output, the string index is -1.  */
    112   bfd_size_type stridxs[1];
    113 };
    114 
    115 
    116 /* The function to create a new entry in the header file hash table.  */
    118 
    119 static struct bfd_hash_entry *
    120 stab_link_includes_newfunc (struct bfd_hash_entry *entry,
    121 			    struct bfd_hash_table *table,
    122 			    const char *string)
    123 {
    124   struct stab_link_includes_entry *ret =
    125     (struct stab_link_includes_entry *) entry;
    126 
    127   /* Allocate the structure if it has not already been allocated by a
    128      subclass.  */
    129   if (ret == NULL)
    130     ret = (struct stab_link_includes_entry *)
    131 	bfd_hash_allocate (table, sizeof (struct stab_link_includes_entry));
    132   if (ret == NULL)
    133     return NULL;
    134 
    135   /* Call the allocation method of the superclass.  */
    136   ret = ((struct stab_link_includes_entry *)
    137 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
    138   if (ret)
    139     /* Set local fields.  */
    140     ret->totals = NULL;
    141 
    142   return (struct bfd_hash_entry *) ret;
    143 }
    144 
    145 /* This function is called for each input file from the add_symbols
    147    pass of the linker.  */
    148 
    149 bool
    150 _bfd_link_section_stabs (bfd *abfd,
    151 			 struct stab_info *sinfo,
    152 			 asection *stabsec,
    153 			 asection *stabstrsec,
    154 			 void * *psecinfo,
    155 			 bfd_size_type *pstring_offset)
    156 {
    157   bool first;
    158   bfd_size_type count, amt;
    159   struct stab_section_info *secinfo;
    160   bfd_byte *stabbuf = NULL;
    161   bfd_byte *stabstrbuf = NULL;
    162   bfd_byte *sym, *symend;
    163   bfd_size_type stroff, next_stroff, skip;
    164   bfd_size_type *pstridx;
    165 
    166   if (stabsec->size == 0
    167       || stabstrsec->size == 0)
    168     /* This file does not contain stabs debugging information.  */
    169     return true;
    170 
    171   if (stabsec->size % STABSIZE != 0)
    172     /* Something is wrong with the format of these stab symbols.
    173        Don't try to optimize them.  */
    174     return true;
    175 
    176   if ((stabstrsec->flags & SEC_RELOC) != 0)
    177     /* We shouldn't see relocations in the strings, and we aren't
    178        prepared to handle them.  */
    179     return true;
    180 
    181   if (bfd_is_abs_section (stabsec->output_section)
    182       || bfd_is_abs_section (stabstrsec->output_section))
    183     /* At least one of the sections is being discarded from the
    184        link, so we should just ignore them.  */
    185     return true;
    186 
    187   first = false;
    188 
    189   if (sinfo->stabstr == NULL)
    190     {
    191       flagword flags;
    192 
    193       /* Initialize the stabs information we need to keep track of.  */
    194       first = true;
    195       sinfo->strings = _bfd_stringtab_init ();
    196       if (sinfo->strings == NULL)
    197 	goto error_return;
    198       /* Make sure the first byte is zero.  */
    199       (void) _bfd_stringtab_add (sinfo->strings, "", true, true);
    200       if (! bfd_hash_table_init (&sinfo->includes,
    201 				 stab_link_includes_newfunc,
    202 				 sizeof (struct stab_link_includes_entry)))
    203 	goto error_return;
    204       flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
    205 	       | SEC_LINKER_CREATED);
    206       sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
    207 							   flags);
    208       if (sinfo->stabstr == NULL)
    209 	goto error_return;
    210     }
    211 
    212   /* Initialize the information we are going to store for this .stab
    213      section.  */
    214   count = stabsec->size / STABSIZE;
    215 
    216   amt = sizeof (struct stab_section_info);
    217   amt += (count - 1) * sizeof (bfd_size_type);
    218   *psecinfo = bfd_alloc (abfd, amt);
    219   if (*psecinfo == NULL)
    220     goto error_return;
    221 
    222   secinfo = (struct stab_section_info *) *psecinfo;
    223   secinfo->excls = NULL;
    224   stabsec->rawsize = stabsec->size;
    225   secinfo->cumulative_skips = NULL;
    226   memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
    227 
    228   /* Read the stabs information from abfd.  */
    229   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
    230       || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
    231     goto error_return;
    232 
    233   /* Look through the stabs symbols, work out the new string indices,
    234      and identify N_BINCL symbols which can be eliminated.  */
    235   stroff = 0;
    236   /* The stabs sections can be split when
    237      -split-by-reloc/-split-by-file is used.  We must keep track of
    238      each stab section's place in the single concatenated string
    239      table.  */
    240   next_stroff = pstring_offset ? *pstring_offset : 0;
    241   skip = 0;
    242 
    243   symend = stabbuf + stabsec->size;
    244   for (sym = stabbuf, pstridx = secinfo->stridxs;
    245        sym < symend;
    246        sym += STABSIZE, ++pstridx)
    247     {
    248       bfd_size_type symstroff;
    249       int type;
    250       const char *string;
    251 
    252       if (*pstridx != 0)
    253 	/* This symbol has already been handled by an N_BINCL pass.  */
    254 	continue;
    255 
    256       type = sym[TYPEOFF];
    257 
    258       if (type == 0)
    259 	{
    260 	  /* Special type 0 stabs indicate the offset to the next
    261 	     string table.  We only copy the very first one.  */
    262 	  stroff = next_stroff;
    263 	  next_stroff += bfd_get_32 (abfd, sym + 8);
    264 	  if (pstring_offset)
    265 	    *pstring_offset = next_stroff;
    266 	  if (! first)
    267 	    {
    268 	      *pstridx = (bfd_size_type) -1;
    269 	      ++skip;
    270 	      continue;
    271 	    }
    272 	  first = false;
    273 	}
    274 
    275       /* Store the string in the hash table, and record the index.  */
    276       symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
    277       if (symstroff >= stabstrsec->size)
    278 	{
    279 	  _bfd_error_handler
    280 	    /* xgettext:c-format */
    281 	    (_("%pB(%pA+%#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 = (char *) 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 = (struct stab_excl_list *) 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 = (struct stab_link_includes_totals *)
    394 		  bfd_hash_allocate (&sinfo->includes, sizeof *t);
    395 	      if (t == NULL)
    396 		goto error_return;
    397 	      t->sum_chars = sum_chars;
    398 	      t->num_chars = num_chars;
    399 	      /* Trim data down.  */
    400 	      t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
    401 	      t->next = incl_entry->totals;
    402 	      incl_entry->totals = t;
    403 	    }
    404 	  else
    405 	    {
    406 	      bfd_size_type *incl_pstridx;
    407 
    408 	      /* We have seen this header file before.  Tell the final
    409 		 pass to change the type to N_EXCL.  */
    410 	      ne->type = (int) N_EXCL;
    411 
    412 	      /* Free off superfluous symbols.  */
    413 	      free (symb);
    414 
    415 	      /* Mark the skipped symbols.  */
    416 
    417 	      nest = 0;
    418 	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
    419 		   incl_sym < symend;
    420 		   incl_sym += STABSIZE, ++incl_pstridx)
    421 		{
    422 		  int incl_type;
    423 
    424 		  incl_type = incl_sym[TYPEOFF];
    425 
    426 		  if (incl_type == (int) N_EINCL)
    427 		    {
    428 		      if (nest == 0)
    429 			{
    430 			  *incl_pstridx = (bfd_size_type) -1;
    431 			  ++skip;
    432 			  break;
    433 			}
    434 		      --nest;
    435 		    }
    436 		  else if (incl_type == (int) N_BINCL)
    437 		    ++nest;
    438 		  else if (incl_type == (int) N_EXCL)
    439 		    /* Keep existing exclusion marks.  */
    440 		    continue;
    441 		  else if (nest == 0)
    442 		    {
    443 		      *incl_pstridx = (bfd_size_type) -1;
    444 		      ++skip;
    445 		    }
    446 		}
    447 	    }
    448 	}
    449     }
    450 
    451   free (stabbuf);
    452   stabbuf = NULL;
    453   free (stabstrbuf);
    454   stabstrbuf = NULL;
    455 
    456   /* We need to set the section sizes such that the linker will
    457      compute the output section sizes correctly.  We set the .stab
    458      size to not include the entries we don't want.  We set
    459      SEC_EXCLUDE for the .stabstr section, so that it will be dropped
    460      from the link.  We record the size of the strtab in the first
    461      .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
    462      for that section.  */
    463   stabsec->size = (count - skip) * STABSIZE;
    464   if (stabsec->size == 0)
    465     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    466   stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    467   sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
    468 
    469   /* Calculate the `cumulative_skips' array now that stabs have been
    470      deleted for this section.  */
    471 
    472   if (skip != 0)
    473     {
    474       bfd_size_type i, offset;
    475       bfd_size_type *pskips;
    476 
    477       amt = count * sizeof (bfd_size_type);
    478       secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
    479       if (secinfo->cumulative_skips == NULL)
    480 	goto error_return;
    481 
    482       pskips = secinfo->cumulative_skips;
    483       pstridx = secinfo->stridxs;
    484       offset = 0;
    485 
    486       for (i = 0; i < count; i++, pskips++, pstridx++)
    487 	{
    488 	  *pskips = offset;
    489 	  if (*pstridx == (bfd_size_type) -1)
    490 	    offset += STABSIZE;
    491 	}
    492 
    493       BFD_ASSERT (offset != 0);
    494     }
    495 
    496   return true;
    497 
    498  error_return:
    499   free (stabbuf);
    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 bool
    512 _bfd_discard_section_stabs (bfd *abfd,
    513 			    asection *stabsec,
    514 			    void * psecinfo,
    515 			    bool (*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_section_stabs.
    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_size_type *) 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   free (stabbuf);
    653   return false;
    654 }
    655 
    656 /* Write out the stab section.  This is called with the relocated
    657    contents.  */
    658 
    659 bool
    660 _bfd_write_section_stabs (bfd *output_bfd,
    661 			  struct stab_info *sinfo,
    662 			  asection *stabsec,
    663 			  void * *psecinfo,
    664 			  bfd_byte *contents)
    665 {
    666   struct stab_section_info *secinfo;
    667   struct stab_excl_list *e;
    668   bfd_byte *sym, *tosym, *symend;
    669   bfd_size_type *pstridx;
    670 
    671   secinfo = (struct stab_section_info *) *psecinfo;
    672 
    673   if (secinfo == NULL)
    674     return bfd_set_section_contents (output_bfd, stabsec->output_section,
    675 				     contents, stabsec->output_offset,
    676 				     stabsec->size);
    677 
    678   /* Handle each N_BINCL entry.  */
    679   for (e = secinfo->excls; e != NULL; e = e->next)
    680     {
    681       bfd_byte *excl_sym;
    682 
    683       BFD_ASSERT (e->offset < stabsec->rawsize);
    684       excl_sym = contents + e->offset;
    685       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
    686       excl_sym[TYPEOFF] = e->type;
    687     }
    688 
    689   /* Copy over all the stabs symbols, omitting the ones we don't want,
    690      and correcting the string indices for those we do want.  */
    691   tosym = contents;
    692   symend = contents + stabsec->rawsize;
    693   for (sym = contents, pstridx = secinfo->stridxs;
    694        sym < symend;
    695        sym += STABSIZE, ++pstridx)
    696     {
    697       if (*pstridx != (bfd_size_type) -1)
    698 	{
    699 	  if (tosym != sym)
    700 	    memcpy (tosym, sym, STABSIZE);
    701 	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
    702 
    703 	  if (sym[TYPEOFF] == 0)
    704 	    {
    705 	      /* This is the header symbol for the stabs section.  We
    706 		 don't really need one, since we have merged all the
    707 		 input stabs sections into one, but we generate one
    708 		 for the benefit of readers which expect to see one.  */
    709 	      BFD_ASSERT (sym == contents);
    710 	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
    711 			  tosym + VALOFF);
    712 	      bfd_put_16 (output_bfd,
    713 			  stabsec->output_section->size / STABSIZE - 1,
    714 			  tosym + DESCOFF);
    715 	    }
    716 
    717 	  tosym += STABSIZE;
    718 	}
    719     }
    720 
    721   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
    722 
    723   return bfd_set_section_contents (output_bfd, stabsec->output_section,
    724 				   contents, (file_ptr) stabsec->output_offset,
    725 				   stabsec->size);
    726 }
    727 
    728 /* Write out the .stabstr section.  */
    729 
    730 bool
    731 _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
    732 {
    733   if (bfd_is_abs_section (sinfo->stabstr->output_section))
    734     /* The section was discarded from the link.  */
    735     return true;
    736 
    737   BFD_ASSERT ((sinfo->stabstr->output_offset
    738 	       + _bfd_stringtab_size (sinfo->strings))
    739 	      <= sinfo->stabstr->output_section->size);
    740 
    741   if (bfd_seek (output_bfd,
    742 		(file_ptr) (sinfo->stabstr->output_section->filepos
    743 			    + sinfo->stabstr->output_offset),
    744 		SEEK_SET) != 0)
    745     return false;
    746 
    747   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
    748     return false;
    749 
    750   /* We no longer need the stabs information.  */
    751   _bfd_stringtab_free (sinfo->strings);
    752   bfd_hash_table_free (&sinfo->includes);
    753 
    754   return true;
    755 }
    756 
    757 /* Adjust an address in the .stab section.  Given OFFSET within
    758    STABSEC, this returns the new offset in the adjusted stab section,
    759    or -1 if the address refers to a stab which has been removed.  */
    760 
    761 bfd_vma
    762 _bfd_stab_section_offset (asection *stabsec,
    763 			  void * psecinfo,
    764 			  bfd_vma offset)
    765 {
    766   struct stab_section_info *secinfo;
    767 
    768   secinfo = (struct stab_section_info *) psecinfo;
    769 
    770   if (secinfo == NULL)
    771     return offset;
    772 
    773   if (offset >= stabsec->rawsize)
    774     return offset - stabsec->rawsize + stabsec->size;
    775 
    776   if (secinfo->cumulative_skips)
    777     {
    778       bfd_vma i;
    779 
    780       i = offset / STABSIZE;
    781 
    782       if (secinfo->stridxs [i] == (bfd_size_type) -1)
    783 	return (bfd_vma) -1;
    784 
    785       return offset - secinfo->cumulative_skips [i];
    786     }
    787 
    788   return offset;
    789 }
    790