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