xref: /netbsd/external/gpl3/gdb/dist/bfd/stabs.c (revision 1424dfb3)
1377e23a2Schristos /* Stabs in sections linking support.
2*1424dfb3Schristos    Copyright (C) 1996-2020 Free Software Foundation, Inc.
3377e23a2Schristos    Written by Ian Lance Taylor, Cygnus Support.
4377e23a2Schristos 
5377e23a2Schristos    This file is part of BFD, the Binary File Descriptor library.
6377e23a2Schristos 
7377e23a2Schristos    This program is free software; you can redistribute it and/or modify
8377e23a2Schristos    it under the terms of the GNU General Public License as published by
9377e23a2Schristos    the Free Software Foundation; either version 3 of the License, or
10377e23a2Schristos    (at your option) any later version.
11377e23a2Schristos 
12377e23a2Schristos    This program is distributed in the hope that it will be useful,
13377e23a2Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14377e23a2Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15377e23a2Schristos    GNU General Public License for more details.
16377e23a2Schristos 
17377e23a2Schristos    You should have received a copy of the GNU General Public License
18377e23a2Schristos    along with this program; if not, write to the Free Software
19377e23a2Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20377e23a2Schristos    MA 02110-1301, USA.  */
21377e23a2Schristos 
22377e23a2Schristos 
23377e23a2Schristos /* This file contains support for linking stabs in sections, as used
24377e23a2Schristos    on COFF and ELF.  */
25377e23a2Schristos 
26377e23a2Schristos #include "sysdep.h"
27377e23a2Schristos #include "bfd.h"
28377e23a2Schristos #include "libbfd.h"
29377e23a2Schristos #include "aout/stab_gnu.h"
30377e23a2Schristos #include "safe-ctype.h"
31377e23a2Schristos 
32377e23a2Schristos /* Stabs entries use a 12 byte format:
33377e23a2Schristos      4 byte string table index
34377e23a2Schristos      1 byte stab type
35377e23a2Schristos      1 byte stab other field
36377e23a2Schristos      2 byte stab desc field
37377e23a2Schristos      4 byte stab value
38377e23a2Schristos    FIXME: This will have to change for a 64 bit object format.
39377e23a2Schristos 
40377e23a2Schristos    The stabs symbols are divided into compilation units.  For the
41377e23a2Schristos    first entry in each unit, the type of 0, the value is the length of
42377e23a2Schristos    the string table for this unit, and the desc field is the number of
43377e23a2Schristos    stabs symbols for this unit.  */
44377e23a2Schristos 
45377e23a2Schristos #define STRDXOFF  0
46377e23a2Schristos #define TYPEOFF   4
47377e23a2Schristos #define OTHEROFF  5
48377e23a2Schristos #define DESCOFF   6
49377e23a2Schristos #define VALOFF    8
50377e23a2Schristos #define STABSIZE  12
51377e23a2Schristos 
52377e23a2Schristos /* A linked list of totals that we have found for a particular header
53377e23a2Schristos    file.  A total is a unique identifier for a particular BINCL...EINCL
54377e23a2Schristos    sequence of STABs that can be used to identify duplicate sequences.
55377e23a2Schristos    It consists of three fields, 'sum_chars' which is the sum of all the
56377e23a2Schristos    STABS characters; 'num_chars' which is the number of these charactes
57377e23a2Schristos    and 'symb' which is a buffer of all the symbols in the sequence.  This
58377e23a2Schristos    buffer is only checked as a last resort.  */
59377e23a2Schristos 
60377e23a2Schristos struct stab_link_includes_totals
61377e23a2Schristos {
62377e23a2Schristos   struct stab_link_includes_totals *next;
63377e23a2Schristos   bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
64377e23a2Schristos   bfd_vma num_chars;  /* Number of STABS characters.  */
65377e23a2Schristos   const char* symb;   /* The STABS characters themselves.  */
66377e23a2Schristos };
67377e23a2Schristos 
68377e23a2Schristos /* An entry in the header file hash table.  */
69377e23a2Schristos 
70377e23a2Schristos struct stab_link_includes_entry
71377e23a2Schristos {
72377e23a2Schristos   struct bfd_hash_entry root;
73377e23a2Schristos   /* List of totals we have found for this file.  */
74377e23a2Schristos   struct stab_link_includes_totals *totals;
75377e23a2Schristos };
76377e23a2Schristos 
77377e23a2Schristos /* This structure is used to hold a list of N_BINCL symbols, some of
78377e23a2Schristos    which might be converted into N_EXCL symbols.  */
79377e23a2Schristos 
80377e23a2Schristos struct stab_excl_list
81377e23a2Schristos {
82377e23a2Schristos   /* The next symbol to convert.  */
83377e23a2Schristos   struct stab_excl_list *next;
84377e23a2Schristos   /* The offset to this symbol in the section contents.  */
85377e23a2Schristos   bfd_size_type offset;
86377e23a2Schristos   /* The value to use for the symbol.  */
87377e23a2Schristos   bfd_vma val;
88377e23a2Schristos   /* The type of this symbol (N_BINCL or N_EXCL).  */
89377e23a2Schristos   int type;
90377e23a2Schristos };
91377e23a2Schristos 
92377e23a2Schristos /* This structure is stored with each .stab section.  */
93377e23a2Schristos 
94377e23a2Schristos struct stab_section_info
95377e23a2Schristos {
96377e23a2Schristos   /* This is a linked list of N_BINCL symbols which should be
97377e23a2Schristos      converted into N_EXCL symbols.  */
98377e23a2Schristos   struct stab_excl_list *excls;
99377e23a2Schristos 
100377e23a2Schristos   /* This is used to map input stab offsets within their sections
101377e23a2Schristos      to output stab offsets, to take into account stabs that have
102377e23a2Schristos      been deleted.  If it is NULL, the output offsets are the same
103377e23a2Schristos      as the input offsets, because no stabs have been deleted from
104377e23a2Schristos      this section.  Otherwise the i'th entry is the number of
105377e23a2Schristos      bytes of stabs that have been deleted prior to the i'th
106377e23a2Schristos      stab.  */
107377e23a2Schristos   bfd_size_type *cumulative_skips;
108377e23a2Schristos 
109377e23a2Schristos   /* This is an array of string indices.  For each stab symbol, we
110377e23a2Schristos      store the string index here.  If a stab symbol should not be
111377e23a2Schristos      included in the final output, the string index is -1.  */
112377e23a2Schristos   bfd_size_type stridxs[1];
113377e23a2Schristos };
114377e23a2Schristos 
115377e23a2Schristos 
116377e23a2Schristos /* The function to create a new entry in the header file hash table.  */
117377e23a2Schristos 
118377e23a2Schristos static struct bfd_hash_entry *
stab_link_includes_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)119377e23a2Schristos stab_link_includes_newfunc (struct bfd_hash_entry *entry,
120377e23a2Schristos 			    struct bfd_hash_table *table,
121377e23a2Schristos 			    const char *string)
122377e23a2Schristos {
123377e23a2Schristos   struct stab_link_includes_entry *ret =
124377e23a2Schristos     (struct stab_link_includes_entry *) entry;
125377e23a2Schristos 
126377e23a2Schristos   /* Allocate the structure if it has not already been allocated by a
127377e23a2Schristos      subclass.  */
128377e23a2Schristos   if (ret == NULL)
129377e23a2Schristos     ret = (struct stab_link_includes_entry *)
130377e23a2Schristos 	bfd_hash_allocate (table, sizeof (struct stab_link_includes_entry));
131377e23a2Schristos   if (ret == NULL)
132377e23a2Schristos     return NULL;
133377e23a2Schristos 
134377e23a2Schristos   /* Call the allocation method of the superclass.  */
135377e23a2Schristos   ret = ((struct stab_link_includes_entry *)
136377e23a2Schristos 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
137377e23a2Schristos   if (ret)
138377e23a2Schristos     /* Set local fields.  */
139377e23a2Schristos     ret->totals = NULL;
140377e23a2Schristos 
141377e23a2Schristos   return (struct bfd_hash_entry *) ret;
142377e23a2Schristos }
143377e23a2Schristos 
144377e23a2Schristos /* This function is called for each input file from the add_symbols
145377e23a2Schristos    pass of the linker.  */
146377e23a2Schristos 
147377e23a2Schristos bfd_boolean
_bfd_link_section_stabs(bfd * abfd,struct stab_info * sinfo,asection * stabsec,asection * stabstrsec,void ** psecinfo,bfd_size_type * pstring_offset)148377e23a2Schristos _bfd_link_section_stabs (bfd *abfd,
149377e23a2Schristos 			 struct stab_info *sinfo,
150377e23a2Schristos 			 asection *stabsec,
151377e23a2Schristos 			 asection *stabstrsec,
152377e23a2Schristos 			 void * *psecinfo,
153377e23a2Schristos 			 bfd_size_type *pstring_offset)
154377e23a2Schristos {
155377e23a2Schristos   bfd_boolean first;
156377e23a2Schristos   bfd_size_type count, amt;
157377e23a2Schristos   struct stab_section_info *secinfo;
158377e23a2Schristos   bfd_byte *stabbuf = NULL;
159377e23a2Schristos   bfd_byte *stabstrbuf = NULL;
160377e23a2Schristos   bfd_byte *sym, *symend;
161377e23a2Schristos   bfd_size_type stroff, next_stroff, skip;
162377e23a2Schristos   bfd_size_type *pstridx;
163377e23a2Schristos 
164377e23a2Schristos   if (stabsec->size == 0
165377e23a2Schristos       || stabstrsec->size == 0)
166377e23a2Schristos     /* This file does not contain stabs debugging information.  */
167377e23a2Schristos     return TRUE;
168377e23a2Schristos 
169377e23a2Schristos   if (stabsec->size % STABSIZE != 0)
170377e23a2Schristos     /* Something is wrong with the format of these stab symbols.
171377e23a2Schristos        Don't try to optimize them.  */
172377e23a2Schristos     return TRUE;
173377e23a2Schristos 
174377e23a2Schristos   if ((stabstrsec->flags & SEC_RELOC) != 0)
175377e23a2Schristos     /* We shouldn't see relocations in the strings, and we aren't
176377e23a2Schristos        prepared to handle them.  */
177377e23a2Schristos     return TRUE;
178377e23a2Schristos 
179377e23a2Schristos   if (bfd_is_abs_section (stabsec->output_section)
180377e23a2Schristos       || bfd_is_abs_section (stabstrsec->output_section))
181377e23a2Schristos     /* At least one of the sections is being discarded from the
182377e23a2Schristos        link, so we should just ignore them.  */
183377e23a2Schristos     return TRUE;
184377e23a2Schristos 
185377e23a2Schristos   first = FALSE;
186377e23a2Schristos 
187377e23a2Schristos   if (sinfo->stabstr == NULL)
188377e23a2Schristos     {
189377e23a2Schristos       flagword flags;
190377e23a2Schristos 
191377e23a2Schristos       /* Initialize the stabs information we need to keep track of.  */
192377e23a2Schristos       first = TRUE;
193377e23a2Schristos       sinfo->strings = _bfd_stringtab_init ();
194377e23a2Schristos       if (sinfo->strings == NULL)
195377e23a2Schristos 	goto error_return;
196377e23a2Schristos       /* Make sure the first byte is zero.  */
197377e23a2Schristos       (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
198377e23a2Schristos       if (! bfd_hash_table_init (&sinfo->includes,
199377e23a2Schristos 				 stab_link_includes_newfunc,
200377e23a2Schristos 				 sizeof (struct stab_link_includes_entry)))
201377e23a2Schristos 	goto error_return;
202377e23a2Schristos       flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
203377e23a2Schristos 	       | SEC_LINKER_CREATED);
204377e23a2Schristos       sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
205377e23a2Schristos 							   flags);
206377e23a2Schristos       if (sinfo->stabstr == NULL)
207377e23a2Schristos 	goto error_return;
208377e23a2Schristos     }
209377e23a2Schristos 
210377e23a2Schristos   /* Initialize the information we are going to store for this .stab
211377e23a2Schristos      section.  */
212377e23a2Schristos   count = stabsec->size / STABSIZE;
213377e23a2Schristos 
214377e23a2Schristos   amt = sizeof (struct stab_section_info);
215377e23a2Schristos   amt += (count - 1) * sizeof (bfd_size_type);
216377e23a2Schristos   *psecinfo = bfd_alloc (abfd, amt);
217377e23a2Schristos   if (*psecinfo == NULL)
218377e23a2Schristos     goto error_return;
219377e23a2Schristos 
220377e23a2Schristos   secinfo = (struct stab_section_info *) *psecinfo;
221377e23a2Schristos   secinfo->excls = NULL;
222377e23a2Schristos   stabsec->rawsize = stabsec->size;
223377e23a2Schristos   secinfo->cumulative_skips = NULL;
224377e23a2Schristos   memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
225377e23a2Schristos 
226377e23a2Schristos   /* Read the stabs information from abfd.  */
227377e23a2Schristos   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
228377e23a2Schristos       || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
229377e23a2Schristos     goto error_return;
230377e23a2Schristos 
231377e23a2Schristos   /* Look through the stabs symbols, work out the new string indices,
232377e23a2Schristos      and identify N_BINCL symbols which can be eliminated.  */
233377e23a2Schristos   stroff = 0;
234377e23a2Schristos   /* The stabs sections can be split when
235377e23a2Schristos      -split-by-reloc/-split-by-file is used.  We must keep track of
236377e23a2Schristos      each stab section's place in the single concatenated string
237377e23a2Schristos      table.  */
238377e23a2Schristos   next_stroff = pstring_offset ? *pstring_offset : 0;
239377e23a2Schristos   skip = 0;
240377e23a2Schristos 
241377e23a2Schristos   symend = stabbuf + stabsec->size;
242377e23a2Schristos   for (sym = stabbuf, pstridx = secinfo->stridxs;
243377e23a2Schristos        sym < symend;
244377e23a2Schristos        sym += STABSIZE, ++pstridx)
245377e23a2Schristos     {
246377e23a2Schristos       bfd_size_type symstroff;
247377e23a2Schristos       int type;
248377e23a2Schristos       const char *string;
249377e23a2Schristos 
250377e23a2Schristos       if (*pstridx != 0)
251377e23a2Schristos 	/* This symbol has already been handled by an N_BINCL pass.  */
252377e23a2Schristos 	continue;
253377e23a2Schristos 
254377e23a2Schristos       type = sym[TYPEOFF];
255377e23a2Schristos 
256377e23a2Schristos       if (type == 0)
257377e23a2Schristos 	{
258377e23a2Schristos 	  /* Special type 0 stabs indicate the offset to the next
259377e23a2Schristos 	     string table.  We only copy the very first one.  */
260377e23a2Schristos 	  stroff = next_stroff;
261377e23a2Schristos 	  next_stroff += bfd_get_32 (abfd, sym + 8);
262377e23a2Schristos 	  if (pstring_offset)
263377e23a2Schristos 	    *pstring_offset = next_stroff;
264377e23a2Schristos 	  if (! first)
265377e23a2Schristos 	    {
266377e23a2Schristos 	      *pstridx = (bfd_size_type) -1;
267377e23a2Schristos 	      ++skip;
268377e23a2Schristos 	      continue;
269377e23a2Schristos 	    }
270377e23a2Schristos 	  first = FALSE;
271377e23a2Schristos 	}
272377e23a2Schristos 
273377e23a2Schristos       /* Store the string in the hash table, and record the index.  */
274377e23a2Schristos       symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
275377e23a2Schristos       if (symstroff >= stabstrsec->size)
276377e23a2Schristos 	{
2771c468f90Schristos 	  _bfd_error_handler
2781c468f90Schristos 	    /* xgettext:c-format */
27907163879Schristos 	    (_("%pB(%pA+%#lx): stabs entry has invalid string index"),
280377e23a2Schristos 	     abfd, stabsec, (long) (sym - stabbuf));
281377e23a2Schristos 	  bfd_set_error (bfd_error_bad_value);
282377e23a2Schristos 	  goto error_return;
283377e23a2Schristos 	}
284377e23a2Schristos       string = (char *) stabstrbuf + symstroff;
285377e23a2Schristos       *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
286377e23a2Schristos 
287377e23a2Schristos       /* An N_BINCL symbol indicates the start of the stabs entries
288377e23a2Schristos 	 for a header file.  We need to scan ahead to the next N_EINCL
289377e23a2Schristos 	 symbol, ignoring nesting, adding up all the characters in the
290377e23a2Schristos 	 symbol names, not including the file numbers in types (the
291377e23a2Schristos 	 first number after an open parenthesis).  */
292377e23a2Schristos       if (type == (int) N_BINCL)
293377e23a2Schristos 	{
294377e23a2Schristos 	  bfd_vma sum_chars;
295377e23a2Schristos 	  bfd_vma num_chars;
296377e23a2Schristos 	  bfd_vma buf_len = 0;
297377e23a2Schristos 	  char * symb;
298377e23a2Schristos 	  char * symb_rover;
299377e23a2Schristos 	  int nest;
300377e23a2Schristos 	  bfd_byte * incl_sym;
301377e23a2Schristos 	  struct stab_link_includes_entry * incl_entry;
302377e23a2Schristos 	  struct stab_link_includes_totals * t;
303377e23a2Schristos 	  struct stab_excl_list * ne;
304377e23a2Schristos 
305377e23a2Schristos 	  symb = symb_rover = NULL;
306377e23a2Schristos 	  sum_chars = num_chars = 0;
307377e23a2Schristos 	  nest = 0;
308377e23a2Schristos 
309377e23a2Schristos 	  for (incl_sym = sym + STABSIZE;
310377e23a2Schristos 	       incl_sym < symend;
311377e23a2Schristos 	       incl_sym += STABSIZE)
312377e23a2Schristos 	    {
313377e23a2Schristos 	      int incl_type;
314377e23a2Schristos 
315377e23a2Schristos 	      incl_type = incl_sym[TYPEOFF];
316377e23a2Schristos 	      if (incl_type == 0)
317377e23a2Schristos 		break;
318377e23a2Schristos 	      else if (incl_type == (int) N_EXCL)
319377e23a2Schristos 		continue;
320377e23a2Schristos 	      else if (incl_type == (int) N_EINCL)
321377e23a2Schristos 		{
322377e23a2Schristos 		  if (nest == 0)
323377e23a2Schristos 		    break;
324377e23a2Schristos 		  --nest;
325377e23a2Schristos 		}
326377e23a2Schristos 	      else if (incl_type == (int) N_BINCL)
327377e23a2Schristos 		++nest;
328377e23a2Schristos 	      else if (nest == 0)
329377e23a2Schristos 		{
330377e23a2Schristos 		  const char *str;
331377e23a2Schristos 
332377e23a2Schristos 		  str = ((char *) stabstrbuf
333377e23a2Schristos 			 + stroff
334377e23a2Schristos 			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
335377e23a2Schristos 		  for (; *str != '\0'; str++)
336377e23a2Schristos 		    {
337377e23a2Schristos 		      if (num_chars >= buf_len)
338377e23a2Schristos 			{
339377e23a2Schristos 			  buf_len += 32 * 1024;
340377e23a2Schristos 			  symb = (char *) bfd_realloc_or_free (symb, buf_len);
341377e23a2Schristos 			  if (symb == NULL)
342377e23a2Schristos 			    goto error_return;
343377e23a2Schristos 			  symb_rover = symb + num_chars;
344377e23a2Schristos 			}
345377e23a2Schristos 		      * symb_rover ++ = * str;
346377e23a2Schristos 		      sum_chars += *str;
347377e23a2Schristos 		      num_chars ++;
348377e23a2Schristos 		      if (*str == '(')
349377e23a2Schristos 			{
350377e23a2Schristos 			  /* Skip the file number.  */
351377e23a2Schristos 			  ++str;
352377e23a2Schristos 			  while (ISDIGIT (*str))
353377e23a2Schristos 			    ++str;
354377e23a2Schristos 			  --str;
355377e23a2Schristos 			}
356377e23a2Schristos 		    }
357377e23a2Schristos 		}
358377e23a2Schristos 	    }
359377e23a2Schristos 
360377e23a2Schristos 	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
361377e23a2Schristos 
362377e23a2Schristos 	  /* If we have already included a header file with the same
363377e23a2Schristos 	     value, then replaced this one with an N_EXCL symbol.  */
364377e23a2Schristos 	  incl_entry = (struct stab_link_includes_entry * )
365377e23a2Schristos 	    bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
366377e23a2Schristos 	  if (incl_entry == NULL)
367377e23a2Schristos 	    goto error_return;
368377e23a2Schristos 
369377e23a2Schristos 	  for (t = incl_entry->totals; t != NULL; t = t->next)
370377e23a2Schristos 	    if (t->sum_chars == sum_chars
371377e23a2Schristos 		&& t->num_chars == num_chars
372377e23a2Schristos 		&& memcmp (t->symb, symb, num_chars) == 0)
373377e23a2Schristos 	      break;
374377e23a2Schristos 
375377e23a2Schristos 	  /* Record this symbol, so that we can set the value
376377e23a2Schristos 	     correctly.  */
377377e23a2Schristos 	  amt = sizeof *ne;
378377e23a2Schristos 	  ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
379377e23a2Schristos 	  if (ne == NULL)
380377e23a2Schristos 	    goto error_return;
381377e23a2Schristos 	  ne->offset = sym - stabbuf;
382377e23a2Schristos 	  ne->val = sum_chars;
383377e23a2Schristos 	  ne->type = (int) N_BINCL;
384377e23a2Schristos 	  ne->next = secinfo->excls;
385377e23a2Schristos 	  secinfo->excls = ne;
386377e23a2Schristos 
387377e23a2Schristos 	  if (t == NULL)
388377e23a2Schristos 	    {
389377e23a2Schristos 	      /* This is the first time we have seen this header file
390377e23a2Schristos 		 with this set of stabs strings.  */
391377e23a2Schristos 	      t = (struct stab_link_includes_totals *)
392377e23a2Schristos 		  bfd_hash_allocate (&sinfo->includes, sizeof *t);
393377e23a2Schristos 	      if (t == NULL)
394377e23a2Schristos 		goto error_return;
395377e23a2Schristos 	      t->sum_chars = sum_chars;
396377e23a2Schristos 	      t->num_chars = num_chars;
397377e23a2Schristos 	      /* Trim data down.  */
398377e23a2Schristos 	      t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
399377e23a2Schristos 	      t->next = incl_entry->totals;
400377e23a2Schristos 	      incl_entry->totals = t;
401377e23a2Schristos 	    }
402377e23a2Schristos 	  else
403377e23a2Schristos 	    {
404377e23a2Schristos 	      bfd_size_type *incl_pstridx;
405377e23a2Schristos 
406377e23a2Schristos 	      /* We have seen this header file before.  Tell the final
407377e23a2Schristos 		 pass to change the type to N_EXCL.  */
408377e23a2Schristos 	      ne->type = (int) N_EXCL;
409377e23a2Schristos 
410377e23a2Schristos 	      /* Free off superfluous symbols.  */
411377e23a2Schristos 	      free (symb);
412377e23a2Schristos 
413377e23a2Schristos 	      /* Mark the skipped symbols.  */
414377e23a2Schristos 
415377e23a2Schristos 	      nest = 0;
416377e23a2Schristos 	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
417377e23a2Schristos 		   incl_sym < symend;
418377e23a2Schristos 		   incl_sym += STABSIZE, ++incl_pstridx)
419377e23a2Schristos 		{
420377e23a2Schristos 		  int incl_type;
421377e23a2Schristos 
422377e23a2Schristos 		  incl_type = incl_sym[TYPEOFF];
423377e23a2Schristos 
424377e23a2Schristos 		  if (incl_type == (int) N_EINCL)
425377e23a2Schristos 		    {
426377e23a2Schristos 		      if (nest == 0)
427377e23a2Schristos 			{
428377e23a2Schristos 			  *incl_pstridx = (bfd_size_type) -1;
429377e23a2Schristos 			  ++skip;
430377e23a2Schristos 			  break;
431377e23a2Schristos 			}
432377e23a2Schristos 		      --nest;
433377e23a2Schristos 		    }
434377e23a2Schristos 		  else if (incl_type == (int) N_BINCL)
435377e23a2Schristos 		    ++nest;
436377e23a2Schristos 		  else if (incl_type == (int) N_EXCL)
437377e23a2Schristos 		    /* Keep existing exclusion marks.  */
438377e23a2Schristos 		    continue;
439377e23a2Schristos 		  else if (nest == 0)
440377e23a2Schristos 		    {
441377e23a2Schristos 		      *incl_pstridx = (bfd_size_type) -1;
442377e23a2Schristos 		      ++skip;
443377e23a2Schristos 		    }
444377e23a2Schristos 		}
445377e23a2Schristos 	    }
446377e23a2Schristos 	}
447377e23a2Schristos     }
448377e23a2Schristos 
449377e23a2Schristos   free (stabbuf);
450377e23a2Schristos   stabbuf = NULL;
451377e23a2Schristos   free (stabstrbuf);
452377e23a2Schristos   stabstrbuf = NULL;
453377e23a2Schristos 
454377e23a2Schristos   /* We need to set the section sizes such that the linker will
455377e23a2Schristos      compute the output section sizes correctly.  We set the .stab
456377e23a2Schristos      size to not include the entries we don't want.  We set
457377e23a2Schristos      SEC_EXCLUDE for the .stabstr section, so that it will be dropped
458377e23a2Schristos      from the link.  We record the size of the strtab in the first
459377e23a2Schristos      .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
460377e23a2Schristos      for that section.  */
461377e23a2Schristos   stabsec->size = (count - skip) * STABSIZE;
462377e23a2Schristos   if (stabsec->size == 0)
463377e23a2Schristos     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
464377e23a2Schristos   stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
465377e23a2Schristos   sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
466377e23a2Schristos 
467377e23a2Schristos   /* Calculate the `cumulative_skips' array now that stabs have been
468377e23a2Schristos      deleted for this section.  */
469377e23a2Schristos 
470377e23a2Schristos   if (skip != 0)
471377e23a2Schristos     {
472377e23a2Schristos       bfd_size_type i, offset;
473377e23a2Schristos       bfd_size_type *pskips;
474377e23a2Schristos 
475377e23a2Schristos       amt = count * sizeof (bfd_size_type);
476377e23a2Schristos       secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
477377e23a2Schristos       if (secinfo->cumulative_skips == NULL)
478377e23a2Schristos 	goto error_return;
479377e23a2Schristos 
480377e23a2Schristos       pskips = secinfo->cumulative_skips;
481377e23a2Schristos       pstridx = secinfo->stridxs;
482377e23a2Schristos       offset = 0;
483377e23a2Schristos 
484377e23a2Schristos       for (i = 0; i < count; i++, pskips++, pstridx++)
485377e23a2Schristos 	{
486377e23a2Schristos 	  *pskips = offset;
487377e23a2Schristos 	  if (*pstridx == (bfd_size_type) -1)
488377e23a2Schristos 	    offset += STABSIZE;
489377e23a2Schristos 	}
490377e23a2Schristos 
491377e23a2Schristos       BFD_ASSERT (offset != 0);
492377e23a2Schristos     }
493377e23a2Schristos 
494377e23a2Schristos   return TRUE;
495377e23a2Schristos 
496377e23a2Schristos  error_return:
497377e23a2Schristos   free (stabbuf);
498377e23a2Schristos   free (stabstrbuf);
499377e23a2Schristos   return FALSE;
500377e23a2Schristos }
501377e23a2Schristos 
502377e23a2Schristos /* This function is called for each input file before the stab
503377e23a2Schristos    section is relocated.  It discards stab entries for discarded
504377e23a2Schristos    functions and variables.  The function returns TRUE iff
505377e23a2Schristos    any entries have been deleted.
506377e23a2Schristos */
507377e23a2Schristos 
508377e23a2Schristos bfd_boolean
_bfd_discard_section_stabs(bfd * abfd,asection * stabsec,void * psecinfo,bfd_boolean (* reloc_symbol_deleted_p)(bfd_vma,void *),void * cookie)509377e23a2Schristos _bfd_discard_section_stabs (bfd *abfd,
510377e23a2Schristos 			    asection *stabsec,
511377e23a2Schristos 			    void * psecinfo,
512377e23a2Schristos 			    bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
513377e23a2Schristos 			    void * cookie)
514377e23a2Schristos {
515377e23a2Schristos   bfd_size_type count, amt;
516377e23a2Schristos   struct stab_section_info *secinfo;
517377e23a2Schristos   bfd_byte *stabbuf = NULL;
518377e23a2Schristos   bfd_byte *sym, *symend;
519377e23a2Schristos   bfd_size_type skip;
520377e23a2Schristos   bfd_size_type *pstridx;
521377e23a2Schristos   int deleting;
522377e23a2Schristos 
523377e23a2Schristos   if (stabsec->size == 0)
524377e23a2Schristos     /* This file does not contain stabs debugging information.  */
525377e23a2Schristos     return FALSE;
526377e23a2Schristos 
527377e23a2Schristos   if (stabsec->size % STABSIZE != 0)
528377e23a2Schristos     /* Something is wrong with the format of these stab symbols.
529377e23a2Schristos        Don't try to optimize them.  */
530377e23a2Schristos     return FALSE;
531377e23a2Schristos 
532377e23a2Schristos   if ((stabsec->output_section != NULL
533377e23a2Schristos        && bfd_is_abs_section (stabsec->output_section)))
534377e23a2Schristos     /* At least one of the sections is being discarded from the
535377e23a2Schristos        link, so we should just ignore them.  */
536377e23a2Schristos     return FALSE;
537377e23a2Schristos 
5385e098073Schristos   /* We should have initialized our data in _bfd_link_section_stabs.
539377e23a2Schristos      If there was some bizarre error reading the string sections, though,
540377e23a2Schristos      we might not have.  Bail rather than asserting.  */
541377e23a2Schristos   if (psecinfo == NULL)
542377e23a2Schristos     return FALSE;
543377e23a2Schristos 
544377e23a2Schristos   count = stabsec->rawsize / STABSIZE;
545377e23a2Schristos   secinfo = (struct stab_section_info *) psecinfo;
546377e23a2Schristos 
547377e23a2Schristos   /* Read the stabs information from abfd.  */
548377e23a2Schristos   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
549377e23a2Schristos     goto error_return;
550377e23a2Schristos 
551377e23a2Schristos   /* Look through the stabs symbols and discard any information for
552377e23a2Schristos      discarded functions.  */
553377e23a2Schristos   skip = 0;
554377e23a2Schristos   deleting = -1;
555377e23a2Schristos 
556377e23a2Schristos   symend = stabbuf + stabsec->rawsize;
557377e23a2Schristos   for (sym = stabbuf, pstridx = secinfo->stridxs;
558377e23a2Schristos        sym < symend;
559377e23a2Schristos        sym += STABSIZE, ++pstridx)
560377e23a2Schristos     {
561377e23a2Schristos       int type;
562377e23a2Schristos 
563377e23a2Schristos       if (*pstridx == (bfd_size_type) -1)
564377e23a2Schristos 	/* This stab was deleted in a previous pass.  */
565377e23a2Schristos 	continue;
566377e23a2Schristos 
567377e23a2Schristos       type = sym[TYPEOFF];
568377e23a2Schristos 
569377e23a2Schristos       if (type == (int) N_FUN)
570377e23a2Schristos 	{
571377e23a2Schristos 	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
572377e23a2Schristos 
573377e23a2Schristos 	  if (strx == 0)
574377e23a2Schristos 	    {
575377e23a2Schristos 	      if (deleting)
576377e23a2Schristos 		{
577377e23a2Schristos 		  skip++;
578377e23a2Schristos 		  *pstridx = -1;
579377e23a2Schristos 		}
580377e23a2Schristos 	      deleting = -1;
581377e23a2Schristos 	      continue;
582377e23a2Schristos 	    }
583377e23a2Schristos 	  deleting = 0;
584377e23a2Schristos 	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
585377e23a2Schristos 	    deleting = 1;
586377e23a2Schristos 	}
587377e23a2Schristos 
588377e23a2Schristos       if (deleting == 1)
589377e23a2Schristos 	{
590377e23a2Schristos 	  *pstridx = -1;
591377e23a2Schristos 	  skip++;
592377e23a2Schristos 	}
593377e23a2Schristos       else if (deleting == -1)
594377e23a2Schristos 	{
595377e23a2Schristos 	  /* Outside of a function.  Check for deleted variables.  */
596377e23a2Schristos 	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
597377e23a2Schristos 	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
598377e23a2Schristos 	      {
599377e23a2Schristos 		*pstridx = -1;
600377e23a2Schristos 		skip ++;
601377e23a2Schristos 	      }
602377e23a2Schristos 	  /* We should also check for N_GSYM entries which reference a
603377e23a2Schristos 	     deleted global, but those are less harmful to debuggers
604377e23a2Schristos 	     and would require parsing the stab strings.  */
605377e23a2Schristos 	}
606377e23a2Schristos     }
607377e23a2Schristos 
608377e23a2Schristos   free (stabbuf);
609377e23a2Schristos   stabbuf = NULL;
610377e23a2Schristos 
611377e23a2Schristos   /* Shrink the stabsec as needed.  */
612377e23a2Schristos   stabsec->size -= skip * STABSIZE;
613377e23a2Schristos   if (stabsec->size == 0)
614377e23a2Schristos     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
615377e23a2Schristos 
616377e23a2Schristos   /* Recalculate the `cumulative_skips' array now that stabs have been
617377e23a2Schristos      deleted for this section.  */
618377e23a2Schristos 
619377e23a2Schristos   if (skip != 0)
620377e23a2Schristos     {
621377e23a2Schristos       bfd_size_type i, offset;
622377e23a2Schristos       bfd_size_type *pskips;
623377e23a2Schristos 
624377e23a2Schristos       if (secinfo->cumulative_skips == NULL)
625377e23a2Schristos 	{
626377e23a2Schristos 	  amt = count * sizeof (bfd_size_type);
627377e23a2Schristos 	  secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
628377e23a2Schristos 	  if (secinfo->cumulative_skips == NULL)
629377e23a2Schristos 	    goto error_return;
630377e23a2Schristos 	}
631377e23a2Schristos 
632377e23a2Schristos       pskips = secinfo->cumulative_skips;
633377e23a2Schristos       pstridx = secinfo->stridxs;
634377e23a2Schristos       offset = 0;
635377e23a2Schristos 
636377e23a2Schristos       for (i = 0; i < count; i++, pskips++, pstridx++)
637377e23a2Schristos 	{
638377e23a2Schristos 	  *pskips = offset;
639377e23a2Schristos 	  if (*pstridx == (bfd_size_type) -1)
640377e23a2Schristos 	    offset += STABSIZE;
641377e23a2Schristos 	}
642377e23a2Schristos 
643377e23a2Schristos       BFD_ASSERT (offset != 0);
644377e23a2Schristos     }
645377e23a2Schristos 
646377e23a2Schristos   return skip > 0;
647377e23a2Schristos 
648377e23a2Schristos  error_return:
649377e23a2Schristos   free (stabbuf);
650377e23a2Schristos   return FALSE;
651377e23a2Schristos }
652377e23a2Schristos 
653377e23a2Schristos /* Write out the stab section.  This is called with the relocated
654377e23a2Schristos    contents.  */
655377e23a2Schristos 
656377e23a2Schristos bfd_boolean
_bfd_write_section_stabs(bfd * output_bfd,struct stab_info * sinfo,asection * stabsec,void ** psecinfo,bfd_byte * contents)657377e23a2Schristos _bfd_write_section_stabs (bfd *output_bfd,
658377e23a2Schristos 			  struct stab_info *sinfo,
659377e23a2Schristos 			  asection *stabsec,
660377e23a2Schristos 			  void * *psecinfo,
661377e23a2Schristos 			  bfd_byte *contents)
662377e23a2Schristos {
663377e23a2Schristos   struct stab_section_info *secinfo;
664377e23a2Schristos   struct stab_excl_list *e;
665377e23a2Schristos   bfd_byte *sym, *tosym, *symend;
666377e23a2Schristos   bfd_size_type *pstridx;
667377e23a2Schristos 
668377e23a2Schristos   secinfo = (struct stab_section_info *) *psecinfo;
669377e23a2Schristos 
670377e23a2Schristos   if (secinfo == NULL)
671377e23a2Schristos     return bfd_set_section_contents (output_bfd, stabsec->output_section,
672377e23a2Schristos 				     contents, stabsec->output_offset,
673377e23a2Schristos 				     stabsec->size);
674377e23a2Schristos 
675377e23a2Schristos   /* Handle each N_BINCL entry.  */
676377e23a2Schristos   for (e = secinfo->excls; e != NULL; e = e->next)
677377e23a2Schristos     {
678377e23a2Schristos       bfd_byte *excl_sym;
679377e23a2Schristos 
680377e23a2Schristos       BFD_ASSERT (e->offset < stabsec->rawsize);
681377e23a2Schristos       excl_sym = contents + e->offset;
682377e23a2Schristos       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
683377e23a2Schristos       excl_sym[TYPEOFF] = e->type;
684377e23a2Schristos     }
685377e23a2Schristos 
686377e23a2Schristos   /* Copy over all the stabs symbols, omitting the ones we don't want,
687377e23a2Schristos      and correcting the string indices for those we do want.  */
688377e23a2Schristos   tosym = contents;
689377e23a2Schristos   symend = contents + stabsec->rawsize;
690377e23a2Schristos   for (sym = contents, pstridx = secinfo->stridxs;
691377e23a2Schristos        sym < symend;
692377e23a2Schristos        sym += STABSIZE, ++pstridx)
693377e23a2Schristos     {
694377e23a2Schristos       if (*pstridx != (bfd_size_type) -1)
695377e23a2Schristos 	{
696377e23a2Schristos 	  if (tosym != sym)
697377e23a2Schristos 	    memcpy (tosym, sym, STABSIZE);
698377e23a2Schristos 	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
699377e23a2Schristos 
700377e23a2Schristos 	  if (sym[TYPEOFF] == 0)
701377e23a2Schristos 	    {
702377e23a2Schristos 	      /* This is the header symbol for the stabs section.  We
703377e23a2Schristos 		 don't really need one, since we have merged all the
704377e23a2Schristos 		 input stabs sections into one, but we generate one
705377e23a2Schristos 		 for the benefit of readers which expect to see one.  */
706377e23a2Schristos 	      BFD_ASSERT (sym == contents);
707377e23a2Schristos 	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
708377e23a2Schristos 			  tosym + VALOFF);
709377e23a2Schristos 	      bfd_put_16 (output_bfd,
710377e23a2Schristos 			  stabsec->output_section->size / STABSIZE - 1,
711377e23a2Schristos 			  tosym + DESCOFF);
712377e23a2Schristos 	    }
713377e23a2Schristos 
714377e23a2Schristos 	  tosym += STABSIZE;
715377e23a2Schristos 	}
716377e23a2Schristos     }
717377e23a2Schristos 
718377e23a2Schristos   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
719377e23a2Schristos 
720377e23a2Schristos   return bfd_set_section_contents (output_bfd, stabsec->output_section,
721377e23a2Schristos 				   contents, (file_ptr) stabsec->output_offset,
722377e23a2Schristos 				   stabsec->size);
723377e23a2Schristos }
724377e23a2Schristos 
725377e23a2Schristos /* Write out the .stabstr section.  */
726377e23a2Schristos 
727377e23a2Schristos bfd_boolean
_bfd_write_stab_strings(bfd * output_bfd,struct stab_info * sinfo)728377e23a2Schristos _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
729377e23a2Schristos {
730377e23a2Schristos   if (bfd_is_abs_section (sinfo->stabstr->output_section))
731377e23a2Schristos     /* The section was discarded from the link.  */
732377e23a2Schristos     return TRUE;
733377e23a2Schristos 
734377e23a2Schristos   BFD_ASSERT ((sinfo->stabstr->output_offset
735377e23a2Schristos 	       + _bfd_stringtab_size (sinfo->strings))
736377e23a2Schristos 	      <= sinfo->stabstr->output_section->size);
737377e23a2Schristos 
738377e23a2Schristos   if (bfd_seek (output_bfd,
739377e23a2Schristos 		(file_ptr) (sinfo->stabstr->output_section->filepos
740377e23a2Schristos 			    + sinfo->stabstr->output_offset),
741377e23a2Schristos 		SEEK_SET) != 0)
742377e23a2Schristos     return FALSE;
743377e23a2Schristos 
744377e23a2Schristos   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
745377e23a2Schristos     return FALSE;
746377e23a2Schristos 
747377e23a2Schristos   /* We no longer need the stabs information.  */
748377e23a2Schristos   _bfd_stringtab_free (sinfo->strings);
749377e23a2Schristos   bfd_hash_table_free (&sinfo->includes);
750377e23a2Schristos 
751377e23a2Schristos   return TRUE;
752377e23a2Schristos }
753377e23a2Schristos 
754377e23a2Schristos /* Adjust an address in the .stab section.  Given OFFSET within
755377e23a2Schristos    STABSEC, this returns the new offset in the adjusted stab section,
756377e23a2Schristos    or -1 if the address refers to a stab which has been removed.  */
757377e23a2Schristos 
758377e23a2Schristos bfd_vma
_bfd_stab_section_offset(asection * stabsec,void * psecinfo,bfd_vma offset)759377e23a2Schristos _bfd_stab_section_offset (asection *stabsec,
760377e23a2Schristos 			  void * psecinfo,
761377e23a2Schristos 			  bfd_vma offset)
762377e23a2Schristos {
763377e23a2Schristos   struct stab_section_info *secinfo;
764377e23a2Schristos 
765377e23a2Schristos   secinfo = (struct stab_section_info *) psecinfo;
766377e23a2Schristos 
767377e23a2Schristos   if (secinfo == NULL)
768377e23a2Schristos     return offset;
769377e23a2Schristos 
770377e23a2Schristos   if (offset >= stabsec->rawsize)
771377e23a2Schristos     return offset - stabsec->rawsize + stabsec->size;
772377e23a2Schristos 
773377e23a2Schristos   if (secinfo->cumulative_skips)
774377e23a2Schristos     {
775377e23a2Schristos       bfd_vma i;
776377e23a2Schristos 
777377e23a2Schristos       i = offset / STABSIZE;
778377e23a2Schristos 
779377e23a2Schristos       if (secinfo->stridxs [i] == (bfd_size_type) -1)
780377e23a2Schristos 	return (bfd_vma) -1;
781377e23a2Schristos 
782377e23a2Schristos       return offset - secinfo->cumulative_skips [i];
783377e23a2Schristos     }
784377e23a2Schristos 
785377e23a2Schristos   return offset;
786377e23a2Schristos }
787