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