Home | History | Annotate | Line # | Download | only in bfd
stabs.c revision 1.6
      1 /* Stabs in sections linking support.
      2    Copyright (C) 1996-2018 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 bfd_boolean
    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   bfd_boolean 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   if (stabbuf != NULL)
    500     free (stabbuf);
    501   if (stabstrbuf != NULL)
    502     free (stabstrbuf);
    503   return FALSE;
    504 }
    505 
    506 /* This function is called for each input file before the stab
    508    section is relocated.  It discards stab entries for discarded
    509    functions and variables.  The function returns TRUE iff
    510    any entries have been deleted.
    511 */
    512 
    513 bfd_boolean
    514 _bfd_discard_section_stabs (bfd *abfd,
    515 			    asection *stabsec,
    516 			    void * psecinfo,
    517 			    bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
    518 			    void * cookie)
    519 {
    520   bfd_size_type count, amt;
    521   struct stab_section_info *secinfo;
    522   bfd_byte *stabbuf = NULL;
    523   bfd_byte *sym, *symend;
    524   bfd_size_type skip;
    525   bfd_size_type *pstridx;
    526   int deleting;
    527 
    528   if (stabsec->size == 0)
    529     /* This file does not contain stabs debugging information.  */
    530     return FALSE;
    531 
    532   if (stabsec->size % STABSIZE != 0)
    533     /* Something is wrong with the format of these stab symbols.
    534        Don't try to optimize them.  */
    535     return FALSE;
    536 
    537   if ((stabsec->output_section != NULL
    538        && bfd_is_abs_section (stabsec->output_section)))
    539     /* At least one of the sections is being discarded from the
    540        link, so we should just ignore them.  */
    541     return FALSE;
    542 
    543   /* We should have initialized our data in _bfd_link_section_stabs.
    544      If there was some bizarre error reading the string sections, though,
    545      we might not have.  Bail rather than asserting.  */
    546   if (psecinfo == NULL)
    547     return FALSE;
    548 
    549   count = stabsec->rawsize / STABSIZE;
    550   secinfo = (struct stab_section_info *) psecinfo;
    551 
    552   /* Read the stabs information from abfd.  */
    553   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
    554     goto error_return;
    555 
    556   /* Look through the stabs symbols and discard any information for
    557      discarded functions.  */
    558   skip = 0;
    559   deleting = -1;
    560 
    561   symend = stabbuf + stabsec->rawsize;
    562   for (sym = stabbuf, pstridx = secinfo->stridxs;
    563        sym < symend;
    564        sym += STABSIZE, ++pstridx)
    565     {
    566       int type;
    567 
    568       if (*pstridx == (bfd_size_type) -1)
    569 	/* This stab was deleted in a previous pass.  */
    570 	continue;
    571 
    572       type = sym[TYPEOFF];
    573 
    574       if (type == (int) N_FUN)
    575 	{
    576 	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
    577 
    578 	  if (strx == 0)
    579 	    {
    580 	      if (deleting)
    581 		{
    582 		  skip++;
    583 		  *pstridx = -1;
    584 		}
    585 	      deleting = -1;
    586 	      continue;
    587 	    }
    588 	  deleting = 0;
    589 	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
    590 	    deleting = 1;
    591 	}
    592 
    593       if (deleting == 1)
    594 	{
    595 	  *pstridx = -1;
    596 	  skip++;
    597 	}
    598       else if (deleting == -1)
    599 	{
    600 	  /* Outside of a function.  Check for deleted variables.  */
    601 	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
    602 	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
    603 	      {
    604 		*pstridx = -1;
    605 		skip ++;
    606 	      }
    607 	  /* We should also check for N_GSYM entries which reference a
    608 	     deleted global, but those are less harmful to debuggers
    609 	     and would require parsing the stab strings.  */
    610 	}
    611     }
    612 
    613   free (stabbuf);
    614   stabbuf = NULL;
    615 
    616   /* Shrink the stabsec as needed.  */
    617   stabsec->size -= skip * STABSIZE;
    618   if (stabsec->size == 0)
    619     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
    620 
    621   /* Recalculate the `cumulative_skips' array now that stabs have been
    622      deleted for this section.  */
    623 
    624   if (skip != 0)
    625     {
    626       bfd_size_type i, offset;
    627       bfd_size_type *pskips;
    628 
    629       if (secinfo->cumulative_skips == NULL)
    630 	{
    631 	  amt = count * sizeof (bfd_size_type);
    632 	  secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
    633 	  if (secinfo->cumulative_skips == NULL)
    634 	    goto error_return;
    635 	}
    636 
    637       pskips = secinfo->cumulative_skips;
    638       pstridx = secinfo->stridxs;
    639       offset = 0;
    640 
    641       for (i = 0; i < count; i++, pskips++, pstridx++)
    642 	{
    643 	  *pskips = offset;
    644 	  if (*pstridx == (bfd_size_type) -1)
    645 	    offset += STABSIZE;
    646 	}
    647 
    648       BFD_ASSERT (offset != 0);
    649     }
    650 
    651   return skip > 0;
    652 
    653  error_return:
    654   if (stabbuf != NULL)
    655     free (stabbuf);
    656   return FALSE;
    657 }
    658 
    659 /* Write out the stab section.  This is called with the relocated
    660    contents.  */
    661 
    662 bfd_boolean
    663 _bfd_write_section_stabs (bfd *output_bfd,
    664 			  struct stab_info *sinfo,
    665 			  asection *stabsec,
    666 			  void * *psecinfo,
    667 			  bfd_byte *contents)
    668 {
    669   struct stab_section_info *secinfo;
    670   struct stab_excl_list *e;
    671   bfd_byte *sym, *tosym, *symend;
    672   bfd_size_type *pstridx;
    673 
    674   secinfo = (struct stab_section_info *) *psecinfo;
    675 
    676   if (secinfo == NULL)
    677     return bfd_set_section_contents (output_bfd, stabsec->output_section,
    678 				     contents, stabsec->output_offset,
    679 				     stabsec->size);
    680 
    681   /* Handle each N_BINCL entry.  */
    682   for (e = secinfo->excls; e != NULL; e = e->next)
    683     {
    684       bfd_byte *excl_sym;
    685 
    686       BFD_ASSERT (e->offset < stabsec->rawsize);
    687       excl_sym = contents + e->offset;
    688       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
    689       excl_sym[TYPEOFF] = e->type;
    690     }
    691 
    692   /* Copy over all the stabs symbols, omitting the ones we don't want,
    693      and correcting the string indices for those we do want.  */
    694   tosym = contents;
    695   symend = contents + stabsec->rawsize;
    696   for (sym = contents, pstridx = secinfo->stridxs;
    697        sym < symend;
    698        sym += STABSIZE, ++pstridx)
    699     {
    700       if (*pstridx != (bfd_size_type) -1)
    701 	{
    702 	  if (tosym != sym)
    703 	    memcpy (tosym, sym, STABSIZE);
    704 	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
    705 
    706 	  if (sym[TYPEOFF] == 0)
    707 	    {
    708 	      /* This is the header symbol for the stabs section.  We
    709 		 don't really need one, since we have merged all the
    710 		 input stabs sections into one, but we generate one
    711 		 for the benefit of readers which expect to see one.  */
    712 	      BFD_ASSERT (sym == contents);
    713 	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
    714 			  tosym + VALOFF);
    715 	      bfd_put_16 (output_bfd,
    716 			  stabsec->output_section->size / STABSIZE - 1,
    717 			  tosym + DESCOFF);
    718 	    }
    719 
    720 	  tosym += STABSIZE;
    721 	}
    722     }
    723 
    724   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
    725 
    726   return bfd_set_section_contents (output_bfd, stabsec->output_section,
    727 				   contents, (file_ptr) stabsec->output_offset,
    728 				   stabsec->size);
    729 }
    730 
    731 /* Write out the .stabstr section.  */
    732 
    733 bfd_boolean
    734 _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
    735 {
    736   if (bfd_is_abs_section (sinfo->stabstr->output_section))
    737     /* The section was discarded from the link.  */
    738     return TRUE;
    739 
    740   BFD_ASSERT ((sinfo->stabstr->output_offset
    741 	       + _bfd_stringtab_size (sinfo->strings))
    742 	      <= sinfo->stabstr->output_section->size);
    743 
    744   if (bfd_seek (output_bfd,
    745 		(file_ptr) (sinfo->stabstr->output_section->filepos
    746 			    + sinfo->stabstr->output_offset),
    747 		SEEK_SET) != 0)
    748     return FALSE;
    749 
    750   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
    751     return FALSE;
    752 
    753   /* We no longer need the stabs information.  */
    754   _bfd_stringtab_free (sinfo->strings);
    755   bfd_hash_table_free (&sinfo->includes);
    756 
    757   return TRUE;
    758 }
    759 
    760 /* Adjust an address in the .stab section.  Given OFFSET within
    761    STABSEC, this returns the new offset in the adjusted stab section,
    762    or -1 if the address refers to a stab which has been removed.  */
    763 
    764 bfd_vma
    765 _bfd_stab_section_offset (asection *stabsec,
    766 			  void * psecinfo,
    767 			  bfd_vma offset)
    768 {
    769   struct stab_section_info *secinfo;
    770 
    771   secinfo = (struct stab_section_info *) psecinfo;
    772 
    773   if (secinfo == NULL)
    774     return offset;
    775 
    776   if (offset >= stabsec->rawsize)
    777     return offset - stabsec->rawsize + stabsec->size;
    778 
    779   if (secinfo->cumulative_skips)
    780     {
    781       bfd_vma i;
    782 
    783       i = offset / STABSIZE;
    784 
    785       if (secinfo->stridxs [i] == (bfd_size_type) -1)
    786 	return (bfd_vma) -1;
    787 
    788       return offset - secinfo->cumulative_skips [i];
    789     }
    790 
    791   return offset;
    792 }
    793