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