xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/stabs.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Stabs in sections linking support.
2*e992f068Schristos    Copyright (C) 1996-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Written by Ian Lance Taylor, Cygnus Support.
475fd0b74Schristos 
575fd0b74Schristos    This file is part of BFD, the Binary File Descriptor library.
675fd0b74Schristos 
775fd0b74Schristos    This program is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1075fd0b74Schristos    (at your option) any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    This program is distributed in the hope that it will be useful,
1375fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1475fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575fd0b74Schristos    GNU General Public License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos 
2375fd0b74Schristos /* This file contains support for linking stabs in sections, as used
2475fd0b74Schristos    on COFF and ELF.  */
2575fd0b74Schristos 
2675fd0b74Schristos #include "sysdep.h"
2775fd0b74Schristos #include "bfd.h"
2875fd0b74Schristos #include "libbfd.h"
2975fd0b74Schristos #include "aout/stab_gnu.h"
3075fd0b74Schristos #include "safe-ctype.h"
3175fd0b74Schristos 
3275fd0b74Schristos /* Stabs entries use a 12 byte format:
3375fd0b74Schristos      4 byte string table index
3475fd0b74Schristos      1 byte stab type
3575fd0b74Schristos      1 byte stab other field
3675fd0b74Schristos      2 byte stab desc field
3775fd0b74Schristos      4 byte stab value
3875fd0b74Schristos    FIXME: This will have to change for a 64 bit object format.
3975fd0b74Schristos 
4075fd0b74Schristos    The stabs symbols are divided into compilation units.  For the
4175fd0b74Schristos    first entry in each unit, the type of 0, the value is the length of
4275fd0b74Schristos    the string table for this unit, and the desc field is the number of
4375fd0b74Schristos    stabs symbols for this unit.  */
4475fd0b74Schristos 
4575fd0b74Schristos #define STRDXOFF  0
4675fd0b74Schristos #define TYPEOFF   4
4775fd0b74Schristos #define OTHEROFF  5
4875fd0b74Schristos #define DESCOFF   6
4975fd0b74Schristos #define VALOFF    8
5075fd0b74Schristos #define STABSIZE  12
5175fd0b74Schristos 
5275fd0b74Schristos /* A linked list of totals that we have found for a particular header
5375fd0b74Schristos    file.  A total is a unique identifier for a particular BINCL...EINCL
5475fd0b74Schristos    sequence of STABs that can be used to identify duplicate sequences.
5575fd0b74Schristos    It consists of three fields, 'sum_chars' which is the sum of all the
5675fd0b74Schristos    STABS characters; 'num_chars' which is the number of these charactes
5775fd0b74Schristos    and 'symb' which is a buffer of all the symbols in the sequence.  This
5875fd0b74Schristos    buffer is only checked as a last resort.  */
5975fd0b74Schristos 
6075fd0b74Schristos struct stab_link_includes_totals
6175fd0b74Schristos {
6275fd0b74Schristos   struct stab_link_includes_totals *next;
6375fd0b74Schristos   bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
6475fd0b74Schristos   bfd_vma num_chars;  /* Number of STABS characters.  */
6575fd0b74Schristos   const char* symb;   /* The STABS characters themselves.  */
6675fd0b74Schristos };
6775fd0b74Schristos 
6875fd0b74Schristos /* An entry in the header file hash table.  */
6975fd0b74Schristos 
7075fd0b74Schristos struct stab_link_includes_entry
7175fd0b74Schristos {
7275fd0b74Schristos   struct bfd_hash_entry root;
7375fd0b74Schristos   /* List of totals we have found for this file.  */
7475fd0b74Schristos   struct stab_link_includes_totals *totals;
7575fd0b74Schristos };
7675fd0b74Schristos 
7775fd0b74Schristos /* This structure is used to hold a list of N_BINCL symbols, some of
7875fd0b74Schristos    which might be converted into N_EXCL symbols.  */
7975fd0b74Schristos 
8075fd0b74Schristos struct stab_excl_list
8175fd0b74Schristos {
8275fd0b74Schristos   /* The next symbol to convert.  */
8375fd0b74Schristos   struct stab_excl_list *next;
8475fd0b74Schristos   /* The offset to this symbol in the section contents.  */
8575fd0b74Schristos   bfd_size_type offset;
8675fd0b74Schristos   /* The value to use for the symbol.  */
8775fd0b74Schristos   bfd_vma val;
8875fd0b74Schristos   /* The type of this symbol (N_BINCL or N_EXCL).  */
8975fd0b74Schristos   int type;
9075fd0b74Schristos };
9175fd0b74Schristos 
9275fd0b74Schristos /* This structure is stored with each .stab section.  */
9375fd0b74Schristos 
9475fd0b74Schristos struct stab_section_info
9575fd0b74Schristos {
9675fd0b74Schristos   /* This is a linked list of N_BINCL symbols which should be
9775fd0b74Schristos      converted into N_EXCL symbols.  */
9875fd0b74Schristos   struct stab_excl_list *excls;
9975fd0b74Schristos 
10075fd0b74Schristos   /* This is used to map input stab offsets within their sections
10175fd0b74Schristos      to output stab offsets, to take into account stabs that have
10275fd0b74Schristos      been deleted.  If it is NULL, the output offsets are the same
10375fd0b74Schristos      as the input offsets, because no stabs have been deleted from
10475fd0b74Schristos      this section.  Otherwise the i'th entry is the number of
10575fd0b74Schristos      bytes of stabs that have been deleted prior to the i'th
10675fd0b74Schristos      stab.  */
10775fd0b74Schristos   bfd_size_type *cumulative_skips;
10875fd0b74Schristos 
10975fd0b74Schristos   /* This is an array of string indices.  For each stab symbol, we
11075fd0b74Schristos      store the string index here.  If a stab symbol should not be
11175fd0b74Schristos      included in the final output, the string index is -1.  */
11275fd0b74Schristos   bfd_size_type stridxs[1];
11375fd0b74Schristos };
11475fd0b74Schristos 
11575fd0b74Schristos 
11675fd0b74Schristos /* The function to create a new entry in the header file hash table.  */
11775fd0b74Schristos 
11875fd0b74Schristos static struct bfd_hash_entry *
stab_link_includes_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)11975fd0b74Schristos stab_link_includes_newfunc (struct bfd_hash_entry *entry,
12075fd0b74Schristos 			    struct bfd_hash_table *table,
12175fd0b74Schristos 			    const char *string)
12275fd0b74Schristos {
12375fd0b74Schristos   struct stab_link_includes_entry *ret =
12475fd0b74Schristos     (struct stab_link_includes_entry *) entry;
12575fd0b74Schristos 
12675fd0b74Schristos   /* Allocate the structure if it has not already been allocated by a
12775fd0b74Schristos      subclass.  */
12875fd0b74Schristos   if (ret == NULL)
12975fd0b74Schristos     ret = (struct stab_link_includes_entry *)
13075fd0b74Schristos 	bfd_hash_allocate (table, sizeof (struct stab_link_includes_entry));
13175fd0b74Schristos   if (ret == NULL)
13275fd0b74Schristos     return NULL;
13375fd0b74Schristos 
13475fd0b74Schristos   /* Call the allocation method of the superclass.  */
13575fd0b74Schristos   ret = ((struct stab_link_includes_entry *)
13675fd0b74Schristos 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
13775fd0b74Schristos   if (ret)
13875fd0b74Schristos     /* Set local fields.  */
13975fd0b74Schristos     ret->totals = NULL;
14075fd0b74Schristos 
14175fd0b74Schristos   return (struct bfd_hash_entry *) ret;
14275fd0b74Schristos }
14375fd0b74Schristos 
14475fd0b74Schristos /* This function is called for each input file from the add_symbols
14575fd0b74Schristos    pass of the linker.  */
14675fd0b74Schristos 
147*e992f068Schristos bool
_bfd_link_section_stabs(bfd * abfd,struct stab_info * sinfo,asection * stabsec,asection * stabstrsec,void ** psecinfo,bfd_size_type * pstring_offset)14875fd0b74Schristos _bfd_link_section_stabs (bfd *abfd,
14975fd0b74Schristos 			 struct stab_info *sinfo,
15075fd0b74Schristos 			 asection *stabsec,
15175fd0b74Schristos 			 asection *stabstrsec,
15275fd0b74Schristos 			 void * *psecinfo,
15375fd0b74Schristos 			 bfd_size_type *pstring_offset)
15475fd0b74Schristos {
155*e992f068Schristos   bool first;
15675fd0b74Schristos   bfd_size_type count, amt;
15775fd0b74Schristos   struct stab_section_info *secinfo;
15875fd0b74Schristos   bfd_byte *stabbuf = NULL;
15975fd0b74Schristos   bfd_byte *stabstrbuf = NULL;
16075fd0b74Schristos   bfd_byte *sym, *symend;
16175fd0b74Schristos   bfd_size_type stroff, next_stroff, skip;
16275fd0b74Schristos   bfd_size_type *pstridx;
16375fd0b74Schristos 
16475fd0b74Schristos   if (stabsec->size == 0
16575fd0b74Schristos       || stabstrsec->size == 0)
16675fd0b74Schristos     /* This file does not contain stabs debugging information.  */
167*e992f068Schristos     return true;
16875fd0b74Schristos 
16975fd0b74Schristos   if (stabsec->size % STABSIZE != 0)
17075fd0b74Schristos     /* Something is wrong with the format of these stab symbols.
17175fd0b74Schristos        Don't try to optimize them.  */
172*e992f068Schristos     return true;
17375fd0b74Schristos 
17475fd0b74Schristos   if ((stabstrsec->flags & SEC_RELOC) != 0)
17575fd0b74Schristos     /* We shouldn't see relocations in the strings, and we aren't
17675fd0b74Schristos        prepared to handle them.  */
177*e992f068Schristos     return true;
17875fd0b74Schristos 
17975fd0b74Schristos   if (bfd_is_abs_section (stabsec->output_section)
18075fd0b74Schristos       || bfd_is_abs_section (stabstrsec->output_section))
18175fd0b74Schristos     /* At least one of the sections is being discarded from the
18275fd0b74Schristos        link, so we should just ignore them.  */
183*e992f068Schristos     return true;
18475fd0b74Schristos 
185*e992f068Schristos   first = false;
18675fd0b74Schristos 
18775fd0b74Schristos   if (sinfo->stabstr == NULL)
18875fd0b74Schristos     {
18975fd0b74Schristos       flagword flags;
19075fd0b74Schristos 
19175fd0b74Schristos       /* Initialize the stabs information we need to keep track of.  */
192*e992f068Schristos       first = true;
19375fd0b74Schristos       sinfo->strings = _bfd_stringtab_init ();
19475fd0b74Schristos       if (sinfo->strings == NULL)
19575fd0b74Schristos 	goto error_return;
19675fd0b74Schristos       /* Make sure the first byte is zero.  */
197*e992f068Schristos       (void) _bfd_stringtab_add (sinfo->strings, "", true, true);
19875fd0b74Schristos       if (! bfd_hash_table_init (&sinfo->includes,
19975fd0b74Schristos 				 stab_link_includes_newfunc,
20075fd0b74Schristos 				 sizeof (struct stab_link_includes_entry)))
20175fd0b74Schristos 	goto error_return;
20275fd0b74Schristos       flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
20375fd0b74Schristos 	       | SEC_LINKER_CREATED);
20475fd0b74Schristos       sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
20575fd0b74Schristos 							   flags);
20675fd0b74Schristos       if (sinfo->stabstr == NULL)
20775fd0b74Schristos 	goto error_return;
20875fd0b74Schristos     }
20975fd0b74Schristos 
21075fd0b74Schristos   /* Initialize the information we are going to store for this .stab
21175fd0b74Schristos      section.  */
21275fd0b74Schristos   count = stabsec->size / STABSIZE;
21375fd0b74Schristos 
21475fd0b74Schristos   amt = sizeof (struct stab_section_info);
21575fd0b74Schristos   amt += (count - 1) * sizeof (bfd_size_type);
21675fd0b74Schristos   *psecinfo = bfd_alloc (abfd, amt);
21775fd0b74Schristos   if (*psecinfo == NULL)
21875fd0b74Schristos     goto error_return;
21975fd0b74Schristos 
22075fd0b74Schristos   secinfo = (struct stab_section_info *) *psecinfo;
22175fd0b74Schristos   secinfo->excls = NULL;
22275fd0b74Schristos   stabsec->rawsize = stabsec->size;
22375fd0b74Schristos   secinfo->cumulative_skips = NULL;
22475fd0b74Schristos   memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
22575fd0b74Schristos 
22675fd0b74Schristos   /* Read the stabs information from abfd.  */
22775fd0b74Schristos   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
22875fd0b74Schristos       || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
22975fd0b74Schristos     goto error_return;
23075fd0b74Schristos 
23175fd0b74Schristos   /* Look through the stabs symbols, work out the new string indices,
23275fd0b74Schristos      and identify N_BINCL symbols which can be eliminated.  */
23375fd0b74Schristos   stroff = 0;
23475fd0b74Schristos   /* The stabs sections can be split when
23575fd0b74Schristos      -split-by-reloc/-split-by-file is used.  We must keep track of
23675fd0b74Schristos      each stab section's place in the single concatenated string
23775fd0b74Schristos      table.  */
23875fd0b74Schristos   next_stroff = pstring_offset ? *pstring_offset : 0;
23975fd0b74Schristos   skip = 0;
24075fd0b74Schristos 
24175fd0b74Schristos   symend = stabbuf + stabsec->size;
24275fd0b74Schristos   for (sym = stabbuf, pstridx = secinfo->stridxs;
24375fd0b74Schristos        sym < symend;
24475fd0b74Schristos        sym += STABSIZE, ++pstridx)
24575fd0b74Schristos     {
24675fd0b74Schristos       bfd_size_type symstroff;
24775fd0b74Schristos       int type;
24875fd0b74Schristos       const char *string;
24975fd0b74Schristos 
25075fd0b74Schristos       if (*pstridx != 0)
25175fd0b74Schristos 	/* This symbol has already been handled by an N_BINCL pass.  */
25275fd0b74Schristos 	continue;
25375fd0b74Schristos 
25475fd0b74Schristos       type = sym[TYPEOFF];
25575fd0b74Schristos 
25675fd0b74Schristos       if (type == 0)
25775fd0b74Schristos 	{
25875fd0b74Schristos 	  /* Special type 0 stabs indicate the offset to the next
25975fd0b74Schristos 	     string table.  We only copy the very first one.  */
26075fd0b74Schristos 	  stroff = next_stroff;
26175fd0b74Schristos 	  next_stroff += bfd_get_32 (abfd, sym + 8);
26275fd0b74Schristos 	  if (pstring_offset)
26375fd0b74Schristos 	    *pstring_offset = next_stroff;
26475fd0b74Schristos 	  if (! first)
26575fd0b74Schristos 	    {
26675fd0b74Schristos 	      *pstridx = (bfd_size_type) -1;
26775fd0b74Schristos 	      ++skip;
26875fd0b74Schristos 	      continue;
26975fd0b74Schristos 	    }
270*e992f068Schristos 	  first = false;
27175fd0b74Schristos 	}
27275fd0b74Schristos 
27375fd0b74Schristos       /* Store the string in the hash table, and record the index.  */
27475fd0b74Schristos       symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
27575fd0b74Schristos       if (symstroff >= stabstrsec->size)
27675fd0b74Schristos 	{
277ede78133Schristos 	  _bfd_error_handler
278ede78133Schristos 	    /* xgettext:c-format */
279ede78133Schristos 	    (_("%pB(%pA+%#lx): stabs entry has invalid string index"),
28075fd0b74Schristos 	     abfd, stabsec, (long) (sym - stabbuf));
28175fd0b74Schristos 	  bfd_set_error (bfd_error_bad_value);
28275fd0b74Schristos 	  goto error_return;
28375fd0b74Schristos 	}
28475fd0b74Schristos       string = (char *) stabstrbuf + symstroff;
285*e992f068Schristos       *pstridx = _bfd_stringtab_add (sinfo->strings, string, true, true);
28675fd0b74Schristos 
28775fd0b74Schristos       /* An N_BINCL symbol indicates the start of the stabs entries
28875fd0b74Schristos 	 for a header file.  We need to scan ahead to the next N_EINCL
28975fd0b74Schristos 	 symbol, ignoring nesting, adding up all the characters in the
29075fd0b74Schristos 	 symbol names, not including the file numbers in types (the
29175fd0b74Schristos 	 first number after an open parenthesis).  */
29275fd0b74Schristos       if (type == (int) N_BINCL)
29375fd0b74Schristos 	{
29475fd0b74Schristos 	  bfd_vma sum_chars;
29575fd0b74Schristos 	  bfd_vma num_chars;
29675fd0b74Schristos 	  bfd_vma buf_len = 0;
29775fd0b74Schristos 	  char * symb;
29875fd0b74Schristos 	  char * symb_rover;
29975fd0b74Schristos 	  int nest;
30075fd0b74Schristos 	  bfd_byte * incl_sym;
30175fd0b74Schristos 	  struct stab_link_includes_entry * incl_entry;
30275fd0b74Schristos 	  struct stab_link_includes_totals * t;
30375fd0b74Schristos 	  struct stab_excl_list * ne;
30475fd0b74Schristos 
30575fd0b74Schristos 	  symb = symb_rover = NULL;
30675fd0b74Schristos 	  sum_chars = num_chars = 0;
30775fd0b74Schristos 	  nest = 0;
30875fd0b74Schristos 
30975fd0b74Schristos 	  for (incl_sym = sym + STABSIZE;
31075fd0b74Schristos 	       incl_sym < symend;
31175fd0b74Schristos 	       incl_sym += STABSIZE)
31275fd0b74Schristos 	    {
31375fd0b74Schristos 	      int incl_type;
31475fd0b74Schristos 
31575fd0b74Schristos 	      incl_type = incl_sym[TYPEOFF];
31675fd0b74Schristos 	      if (incl_type == 0)
31775fd0b74Schristos 		break;
31875fd0b74Schristos 	      else if (incl_type == (int) N_EXCL)
31975fd0b74Schristos 		continue;
32075fd0b74Schristos 	      else if (incl_type == (int) N_EINCL)
32175fd0b74Schristos 		{
32275fd0b74Schristos 		  if (nest == 0)
32375fd0b74Schristos 		    break;
32475fd0b74Schristos 		  --nest;
32575fd0b74Schristos 		}
32675fd0b74Schristos 	      else if (incl_type == (int) N_BINCL)
32775fd0b74Schristos 		++nest;
32875fd0b74Schristos 	      else if (nest == 0)
32975fd0b74Schristos 		{
33075fd0b74Schristos 		  const char *str;
33175fd0b74Schristos 
33275fd0b74Schristos 		  str = ((char *) stabstrbuf
33375fd0b74Schristos 			 + stroff
33475fd0b74Schristos 			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
33575fd0b74Schristos 		  for (; *str != '\0'; str++)
33675fd0b74Schristos 		    {
33775fd0b74Schristos 		      if (num_chars >= buf_len)
33875fd0b74Schristos 			{
33975fd0b74Schristos 			  buf_len += 32 * 1024;
34075fd0b74Schristos 			  symb = (char *) bfd_realloc_or_free (symb, buf_len);
34175fd0b74Schristos 			  if (symb == NULL)
34275fd0b74Schristos 			    goto error_return;
34375fd0b74Schristos 			  symb_rover = symb + num_chars;
34475fd0b74Schristos 			}
34575fd0b74Schristos 		      * symb_rover ++ = * str;
34675fd0b74Schristos 		      sum_chars += *str;
34775fd0b74Schristos 		      num_chars ++;
34875fd0b74Schristos 		      if (*str == '(')
34975fd0b74Schristos 			{
35075fd0b74Schristos 			  /* Skip the file number.  */
35175fd0b74Schristos 			  ++str;
35275fd0b74Schristos 			  while (ISDIGIT (*str))
35375fd0b74Schristos 			    ++str;
35475fd0b74Schristos 			  --str;
35575fd0b74Schristos 			}
35675fd0b74Schristos 		    }
35775fd0b74Schristos 		}
35875fd0b74Schristos 	    }
35975fd0b74Schristos 
36075fd0b74Schristos 	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
36175fd0b74Schristos 
36275fd0b74Schristos 	  /* If we have already included a header file with the same
36375fd0b74Schristos 	     value, then replaced this one with an N_EXCL symbol.  */
36475fd0b74Schristos 	  incl_entry = (struct stab_link_includes_entry * )
365*e992f068Schristos 	    bfd_hash_lookup (&sinfo->includes, string, true, true);
36675fd0b74Schristos 	  if (incl_entry == NULL)
36775fd0b74Schristos 	    goto error_return;
36875fd0b74Schristos 
36975fd0b74Schristos 	  for (t = incl_entry->totals; t != NULL; t = t->next)
37075fd0b74Schristos 	    if (t->sum_chars == sum_chars
37175fd0b74Schristos 		&& t->num_chars == num_chars
37275fd0b74Schristos 		&& memcmp (t->symb, symb, num_chars) == 0)
37375fd0b74Schristos 	      break;
37475fd0b74Schristos 
37575fd0b74Schristos 	  /* Record this symbol, so that we can set the value
37675fd0b74Schristos 	     correctly.  */
37775fd0b74Schristos 	  amt = sizeof *ne;
37875fd0b74Schristos 	  ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
37975fd0b74Schristos 	  if (ne == NULL)
38075fd0b74Schristos 	    goto error_return;
38175fd0b74Schristos 	  ne->offset = sym - stabbuf;
38275fd0b74Schristos 	  ne->val = sum_chars;
38375fd0b74Schristos 	  ne->type = (int) N_BINCL;
38475fd0b74Schristos 	  ne->next = secinfo->excls;
38575fd0b74Schristos 	  secinfo->excls = ne;
38675fd0b74Schristos 
38775fd0b74Schristos 	  if (t == NULL)
38875fd0b74Schristos 	    {
38975fd0b74Schristos 	      /* This is the first time we have seen this header file
39075fd0b74Schristos 		 with this set of stabs strings.  */
39175fd0b74Schristos 	      t = (struct stab_link_includes_totals *)
39275fd0b74Schristos 		  bfd_hash_allocate (&sinfo->includes, sizeof *t);
39375fd0b74Schristos 	      if (t == NULL)
39475fd0b74Schristos 		goto error_return;
39575fd0b74Schristos 	      t->sum_chars = sum_chars;
39675fd0b74Schristos 	      t->num_chars = num_chars;
39775fd0b74Schristos 	      /* Trim data down.  */
39875fd0b74Schristos 	      t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
39975fd0b74Schristos 	      t->next = incl_entry->totals;
40075fd0b74Schristos 	      incl_entry->totals = t;
40175fd0b74Schristos 	    }
40275fd0b74Schristos 	  else
40375fd0b74Schristos 	    {
40475fd0b74Schristos 	      bfd_size_type *incl_pstridx;
40575fd0b74Schristos 
40675fd0b74Schristos 	      /* We have seen this header file before.  Tell the final
40775fd0b74Schristos 		 pass to change the type to N_EXCL.  */
40875fd0b74Schristos 	      ne->type = (int) N_EXCL;
40975fd0b74Schristos 
41075fd0b74Schristos 	      /* Free off superfluous symbols.  */
41175fd0b74Schristos 	      free (symb);
41275fd0b74Schristos 
41375fd0b74Schristos 	      /* Mark the skipped symbols.  */
41475fd0b74Schristos 
41575fd0b74Schristos 	      nest = 0;
41675fd0b74Schristos 	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
41775fd0b74Schristos 		   incl_sym < symend;
41875fd0b74Schristos 		   incl_sym += STABSIZE, ++incl_pstridx)
41975fd0b74Schristos 		{
42075fd0b74Schristos 		  int incl_type;
42175fd0b74Schristos 
42275fd0b74Schristos 		  incl_type = incl_sym[TYPEOFF];
42375fd0b74Schristos 
42475fd0b74Schristos 		  if (incl_type == (int) N_EINCL)
42575fd0b74Schristos 		    {
42675fd0b74Schristos 		      if (nest == 0)
42775fd0b74Schristos 			{
42875fd0b74Schristos 			  *incl_pstridx = (bfd_size_type) -1;
42975fd0b74Schristos 			  ++skip;
43075fd0b74Schristos 			  break;
43175fd0b74Schristos 			}
43275fd0b74Schristos 		      --nest;
43375fd0b74Schristos 		    }
43475fd0b74Schristos 		  else if (incl_type == (int) N_BINCL)
43575fd0b74Schristos 		    ++nest;
43675fd0b74Schristos 		  else if (incl_type == (int) N_EXCL)
43775fd0b74Schristos 		    /* Keep existing exclusion marks.  */
43875fd0b74Schristos 		    continue;
43975fd0b74Schristos 		  else if (nest == 0)
44075fd0b74Schristos 		    {
44175fd0b74Schristos 		      *incl_pstridx = (bfd_size_type) -1;
44275fd0b74Schristos 		      ++skip;
44375fd0b74Schristos 		    }
44475fd0b74Schristos 		}
44575fd0b74Schristos 	    }
44675fd0b74Schristos 	}
44775fd0b74Schristos     }
44875fd0b74Schristos 
44975fd0b74Schristos   free (stabbuf);
45075fd0b74Schristos   stabbuf = NULL;
45175fd0b74Schristos   free (stabstrbuf);
45275fd0b74Schristos   stabstrbuf = NULL;
45375fd0b74Schristos 
45475fd0b74Schristos   /* We need to set the section sizes such that the linker will
45575fd0b74Schristos      compute the output section sizes correctly.  We set the .stab
45675fd0b74Schristos      size to not include the entries we don't want.  We set
45775fd0b74Schristos      SEC_EXCLUDE for the .stabstr section, so that it will be dropped
45875fd0b74Schristos      from the link.  We record the size of the strtab in the first
45975fd0b74Schristos      .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
46075fd0b74Schristos      for that section.  */
46175fd0b74Schristos   stabsec->size = (count - skip) * STABSIZE;
46275fd0b74Schristos   if (stabsec->size == 0)
46375fd0b74Schristos     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
46475fd0b74Schristos   stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
46575fd0b74Schristos   sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
46675fd0b74Schristos 
46775fd0b74Schristos   /* Calculate the `cumulative_skips' array now that stabs have been
46875fd0b74Schristos      deleted for this section.  */
46975fd0b74Schristos 
47075fd0b74Schristos   if (skip != 0)
47175fd0b74Schristos     {
47275fd0b74Schristos       bfd_size_type i, offset;
47375fd0b74Schristos       bfd_size_type *pskips;
47475fd0b74Schristos 
47575fd0b74Schristos       amt = count * sizeof (bfd_size_type);
47675fd0b74Schristos       secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
47775fd0b74Schristos       if (secinfo->cumulative_skips == NULL)
47875fd0b74Schristos 	goto error_return;
47975fd0b74Schristos 
48075fd0b74Schristos       pskips = secinfo->cumulative_skips;
48175fd0b74Schristos       pstridx = secinfo->stridxs;
48275fd0b74Schristos       offset = 0;
48375fd0b74Schristos 
48475fd0b74Schristos       for (i = 0; i < count; i++, pskips++, pstridx++)
48575fd0b74Schristos 	{
48675fd0b74Schristos 	  *pskips = offset;
48775fd0b74Schristos 	  if (*pstridx == (bfd_size_type) -1)
48875fd0b74Schristos 	    offset += STABSIZE;
48975fd0b74Schristos 	}
49075fd0b74Schristos 
49175fd0b74Schristos       BFD_ASSERT (offset != 0);
49275fd0b74Schristos     }
49375fd0b74Schristos 
494*e992f068Schristos   return true;
49575fd0b74Schristos 
49675fd0b74Schristos  error_return:
49775fd0b74Schristos   free (stabbuf);
49875fd0b74Schristos   free (stabstrbuf);
499*e992f068Schristos   return false;
50075fd0b74Schristos }
50175fd0b74Schristos 
50275fd0b74Schristos /* This function is called for each input file before the stab
50375fd0b74Schristos    section is relocated.  It discards stab entries for discarded
50475fd0b74Schristos    functions and variables.  The function returns TRUE iff
50575fd0b74Schristos    any entries have been deleted.
50675fd0b74Schristos */
50775fd0b74Schristos 
508*e992f068Schristos bool
_bfd_discard_section_stabs(bfd * abfd,asection * stabsec,void * psecinfo,bool (* reloc_symbol_deleted_p)(bfd_vma,void *),void * cookie)50975fd0b74Schristos _bfd_discard_section_stabs (bfd *abfd,
51075fd0b74Schristos 			    asection *stabsec,
51175fd0b74Schristos 			    void * psecinfo,
512*e992f068Schristos 			    bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
51375fd0b74Schristos 			    void * cookie)
51475fd0b74Schristos {
51575fd0b74Schristos   bfd_size_type count, amt;
51675fd0b74Schristos   struct stab_section_info *secinfo;
51775fd0b74Schristos   bfd_byte *stabbuf = NULL;
51875fd0b74Schristos   bfd_byte *sym, *symend;
51975fd0b74Schristos   bfd_size_type skip;
52075fd0b74Schristos   bfd_size_type *pstridx;
52175fd0b74Schristos   int deleting;
52275fd0b74Schristos 
52375fd0b74Schristos   if (stabsec->size == 0)
52475fd0b74Schristos     /* This file does not contain stabs debugging information.  */
525*e992f068Schristos     return false;
52675fd0b74Schristos 
52775fd0b74Schristos   if (stabsec->size % STABSIZE != 0)
52875fd0b74Schristos     /* Something is wrong with the format of these stab symbols.
52975fd0b74Schristos        Don't try to optimize them.  */
530*e992f068Schristos     return false;
53175fd0b74Schristos 
53275fd0b74Schristos   if ((stabsec->output_section != NULL
53375fd0b74Schristos        && bfd_is_abs_section (stabsec->output_section)))
53475fd0b74Schristos     /* At least one of the sections is being discarded from the
53575fd0b74Schristos        link, so we should just ignore them.  */
536*e992f068Schristos     return false;
53775fd0b74Schristos 
53875fd0b74Schristos   /* We should have initialized our data in _bfd_link_section_stabs.
53975fd0b74Schristos      If there was some bizarre error reading the string sections, though,
54075fd0b74Schristos      we might not have.  Bail rather than asserting.  */
54175fd0b74Schristos   if (psecinfo == NULL)
542*e992f068Schristos     return false;
54375fd0b74Schristos 
54475fd0b74Schristos   count = stabsec->rawsize / STABSIZE;
54575fd0b74Schristos   secinfo = (struct stab_section_info *) psecinfo;
54675fd0b74Schristos 
54775fd0b74Schristos   /* Read the stabs information from abfd.  */
54875fd0b74Schristos   if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
54975fd0b74Schristos     goto error_return;
55075fd0b74Schristos 
55175fd0b74Schristos   /* Look through the stabs symbols and discard any information for
55275fd0b74Schristos      discarded functions.  */
55375fd0b74Schristos   skip = 0;
55475fd0b74Schristos   deleting = -1;
55575fd0b74Schristos 
55675fd0b74Schristos   symend = stabbuf + stabsec->rawsize;
55775fd0b74Schristos   for (sym = stabbuf, pstridx = secinfo->stridxs;
55875fd0b74Schristos        sym < symend;
55975fd0b74Schristos        sym += STABSIZE, ++pstridx)
56075fd0b74Schristos     {
56175fd0b74Schristos       int type;
56275fd0b74Schristos 
56375fd0b74Schristos       if (*pstridx == (bfd_size_type) -1)
56475fd0b74Schristos 	/* This stab was deleted in a previous pass.  */
56575fd0b74Schristos 	continue;
56675fd0b74Schristos 
56775fd0b74Schristos       type = sym[TYPEOFF];
56875fd0b74Schristos 
56975fd0b74Schristos       if (type == (int) N_FUN)
57075fd0b74Schristos 	{
57175fd0b74Schristos 	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
57275fd0b74Schristos 
57375fd0b74Schristos 	  if (strx == 0)
57475fd0b74Schristos 	    {
57575fd0b74Schristos 	      if (deleting)
57675fd0b74Schristos 		{
57775fd0b74Schristos 		  skip++;
57875fd0b74Schristos 		  *pstridx = -1;
57975fd0b74Schristos 		}
58075fd0b74Schristos 	      deleting = -1;
58175fd0b74Schristos 	      continue;
58275fd0b74Schristos 	    }
58375fd0b74Schristos 	  deleting = 0;
58475fd0b74Schristos 	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
58575fd0b74Schristos 	    deleting = 1;
58675fd0b74Schristos 	}
58775fd0b74Schristos 
58875fd0b74Schristos       if (deleting == 1)
58975fd0b74Schristos 	{
59075fd0b74Schristos 	  *pstridx = -1;
59175fd0b74Schristos 	  skip++;
59275fd0b74Schristos 	}
59375fd0b74Schristos       else if (deleting == -1)
59475fd0b74Schristos 	{
59575fd0b74Schristos 	  /* Outside of a function.  Check for deleted variables.  */
59675fd0b74Schristos 	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
59775fd0b74Schristos 	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
59875fd0b74Schristos 	      {
59975fd0b74Schristos 		*pstridx = -1;
60075fd0b74Schristos 		skip ++;
60175fd0b74Schristos 	      }
60275fd0b74Schristos 	  /* We should also check for N_GSYM entries which reference a
60375fd0b74Schristos 	     deleted global, but those are less harmful to debuggers
60475fd0b74Schristos 	     and would require parsing the stab strings.  */
60575fd0b74Schristos 	}
60675fd0b74Schristos     }
60775fd0b74Schristos 
60875fd0b74Schristos   free (stabbuf);
60975fd0b74Schristos   stabbuf = NULL;
61075fd0b74Schristos 
61175fd0b74Schristos   /* Shrink the stabsec as needed.  */
61275fd0b74Schristos   stabsec->size -= skip * STABSIZE;
61375fd0b74Schristos   if (stabsec->size == 0)
61475fd0b74Schristos     stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
61575fd0b74Schristos 
61675fd0b74Schristos   /* Recalculate the `cumulative_skips' array now that stabs have been
61775fd0b74Schristos      deleted for this section.  */
61875fd0b74Schristos 
61975fd0b74Schristos   if (skip != 0)
62075fd0b74Schristos     {
62175fd0b74Schristos       bfd_size_type i, offset;
62275fd0b74Schristos       bfd_size_type *pskips;
62375fd0b74Schristos 
62475fd0b74Schristos       if (secinfo->cumulative_skips == NULL)
62575fd0b74Schristos 	{
62675fd0b74Schristos 	  amt = count * sizeof (bfd_size_type);
62775fd0b74Schristos 	  secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
62875fd0b74Schristos 	  if (secinfo->cumulative_skips == NULL)
62975fd0b74Schristos 	    goto error_return;
63075fd0b74Schristos 	}
63175fd0b74Schristos 
63275fd0b74Schristos       pskips = secinfo->cumulative_skips;
63375fd0b74Schristos       pstridx = secinfo->stridxs;
63475fd0b74Schristos       offset = 0;
63575fd0b74Schristos 
63675fd0b74Schristos       for (i = 0; i < count; i++, pskips++, pstridx++)
63775fd0b74Schristos 	{
63875fd0b74Schristos 	  *pskips = offset;
63975fd0b74Schristos 	  if (*pstridx == (bfd_size_type) -1)
64075fd0b74Schristos 	    offset += STABSIZE;
64175fd0b74Schristos 	}
64275fd0b74Schristos 
64375fd0b74Schristos       BFD_ASSERT (offset != 0);
64475fd0b74Schristos     }
64575fd0b74Schristos 
64675fd0b74Schristos   return skip > 0;
64775fd0b74Schristos 
64875fd0b74Schristos  error_return:
64975fd0b74Schristos   free (stabbuf);
650*e992f068Schristos   return false;
65175fd0b74Schristos }
65275fd0b74Schristos 
65375fd0b74Schristos /* Write out the stab section.  This is called with the relocated
65475fd0b74Schristos    contents.  */
65575fd0b74Schristos 
656*e992f068Schristos bool
_bfd_write_section_stabs(bfd * output_bfd,struct stab_info * sinfo,asection * stabsec,void ** psecinfo,bfd_byte * contents)65775fd0b74Schristos _bfd_write_section_stabs (bfd *output_bfd,
65875fd0b74Schristos 			  struct stab_info *sinfo,
65975fd0b74Schristos 			  asection *stabsec,
66075fd0b74Schristos 			  void * *psecinfo,
66175fd0b74Schristos 			  bfd_byte *contents)
66275fd0b74Schristos {
66375fd0b74Schristos   struct stab_section_info *secinfo;
66475fd0b74Schristos   struct stab_excl_list *e;
66575fd0b74Schristos   bfd_byte *sym, *tosym, *symend;
66675fd0b74Schristos   bfd_size_type *pstridx;
66775fd0b74Schristos 
66875fd0b74Schristos   secinfo = (struct stab_section_info *) *psecinfo;
66975fd0b74Schristos 
67075fd0b74Schristos   if (secinfo == NULL)
67175fd0b74Schristos     return bfd_set_section_contents (output_bfd, stabsec->output_section,
67275fd0b74Schristos 				     contents, stabsec->output_offset,
67375fd0b74Schristos 				     stabsec->size);
67475fd0b74Schristos 
67575fd0b74Schristos   /* Handle each N_BINCL entry.  */
67675fd0b74Schristos   for (e = secinfo->excls; e != NULL; e = e->next)
67775fd0b74Schristos     {
67875fd0b74Schristos       bfd_byte *excl_sym;
67975fd0b74Schristos 
68075fd0b74Schristos       BFD_ASSERT (e->offset < stabsec->rawsize);
68175fd0b74Schristos       excl_sym = contents + e->offset;
68275fd0b74Schristos       bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
68375fd0b74Schristos       excl_sym[TYPEOFF] = e->type;
68475fd0b74Schristos     }
68575fd0b74Schristos 
68675fd0b74Schristos   /* Copy over all the stabs symbols, omitting the ones we don't want,
68775fd0b74Schristos      and correcting the string indices for those we do want.  */
68875fd0b74Schristos   tosym = contents;
68975fd0b74Schristos   symend = contents + stabsec->rawsize;
69075fd0b74Schristos   for (sym = contents, pstridx = secinfo->stridxs;
69175fd0b74Schristos        sym < symend;
69275fd0b74Schristos        sym += STABSIZE, ++pstridx)
69375fd0b74Schristos     {
69475fd0b74Schristos       if (*pstridx != (bfd_size_type) -1)
69575fd0b74Schristos 	{
69675fd0b74Schristos 	  if (tosym != sym)
69775fd0b74Schristos 	    memcpy (tosym, sym, STABSIZE);
69875fd0b74Schristos 	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
69975fd0b74Schristos 
70075fd0b74Schristos 	  if (sym[TYPEOFF] == 0)
70175fd0b74Schristos 	    {
70275fd0b74Schristos 	      /* This is the header symbol for the stabs section.  We
70375fd0b74Schristos 		 don't really need one, since we have merged all the
70475fd0b74Schristos 		 input stabs sections into one, but we generate one
70575fd0b74Schristos 		 for the benefit of readers which expect to see one.  */
70675fd0b74Schristos 	      BFD_ASSERT (sym == contents);
70775fd0b74Schristos 	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
70875fd0b74Schristos 			  tosym + VALOFF);
70975fd0b74Schristos 	      bfd_put_16 (output_bfd,
71075fd0b74Schristos 			  stabsec->output_section->size / STABSIZE - 1,
71175fd0b74Schristos 			  tosym + DESCOFF);
71275fd0b74Schristos 	    }
71375fd0b74Schristos 
71475fd0b74Schristos 	  tosym += STABSIZE;
71575fd0b74Schristos 	}
71675fd0b74Schristos     }
71775fd0b74Schristos 
71875fd0b74Schristos   BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
71975fd0b74Schristos 
72075fd0b74Schristos   return bfd_set_section_contents (output_bfd, stabsec->output_section,
72175fd0b74Schristos 				   contents, (file_ptr) stabsec->output_offset,
72275fd0b74Schristos 				   stabsec->size);
72375fd0b74Schristos }
72475fd0b74Schristos 
72575fd0b74Schristos /* Write out the .stabstr section.  */
72675fd0b74Schristos 
727*e992f068Schristos bool
_bfd_write_stab_strings(bfd * output_bfd,struct stab_info * sinfo)72875fd0b74Schristos _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
72975fd0b74Schristos {
73075fd0b74Schristos   if (bfd_is_abs_section (sinfo->stabstr->output_section))
73175fd0b74Schristos     /* The section was discarded from the link.  */
732*e992f068Schristos     return true;
73375fd0b74Schristos 
73475fd0b74Schristos   BFD_ASSERT ((sinfo->stabstr->output_offset
73575fd0b74Schristos 	       + _bfd_stringtab_size (sinfo->strings))
73675fd0b74Schristos 	      <= sinfo->stabstr->output_section->size);
73775fd0b74Schristos 
73875fd0b74Schristos   if (bfd_seek (output_bfd,
73975fd0b74Schristos 		(file_ptr) (sinfo->stabstr->output_section->filepos
74075fd0b74Schristos 			    + sinfo->stabstr->output_offset),
74175fd0b74Schristos 		SEEK_SET) != 0)
742*e992f068Schristos     return false;
74375fd0b74Schristos 
74475fd0b74Schristos   if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
745*e992f068Schristos     return false;
74675fd0b74Schristos 
74775fd0b74Schristos   /* We no longer need the stabs information.  */
74875fd0b74Schristos   _bfd_stringtab_free (sinfo->strings);
74975fd0b74Schristos   bfd_hash_table_free (&sinfo->includes);
75075fd0b74Schristos 
751*e992f068Schristos   return true;
75275fd0b74Schristos }
75375fd0b74Schristos 
75475fd0b74Schristos /* Adjust an address in the .stab section.  Given OFFSET within
75575fd0b74Schristos    STABSEC, this returns the new offset in the adjusted stab section,
75675fd0b74Schristos    or -1 if the address refers to a stab which has been removed.  */
75775fd0b74Schristos 
75875fd0b74Schristos bfd_vma
_bfd_stab_section_offset(asection * stabsec,void * psecinfo,bfd_vma offset)75975fd0b74Schristos _bfd_stab_section_offset (asection *stabsec,
76075fd0b74Schristos 			  void * psecinfo,
76175fd0b74Schristos 			  bfd_vma offset)
76275fd0b74Schristos {
76375fd0b74Schristos   struct stab_section_info *secinfo;
76475fd0b74Schristos 
76575fd0b74Schristos   secinfo = (struct stab_section_info *) psecinfo;
76675fd0b74Schristos 
76775fd0b74Schristos   if (secinfo == NULL)
76875fd0b74Schristos     return offset;
76975fd0b74Schristos 
77075fd0b74Schristos   if (offset >= stabsec->rawsize)
77175fd0b74Schristos     return offset - stabsec->rawsize + stabsec->size;
77275fd0b74Schristos 
77375fd0b74Schristos   if (secinfo->cumulative_skips)
77475fd0b74Schristos     {
77575fd0b74Schristos       bfd_vma i;
77675fd0b74Schristos 
77775fd0b74Schristos       i = offset / STABSIZE;
77875fd0b74Schristos 
77975fd0b74Schristos       if (secinfo->stridxs [i] == (bfd_size_type) -1)
78075fd0b74Schristos 	return (bfd_vma) -1;
78175fd0b74Schristos 
78275fd0b74Schristos       return offset - secinfo->cumulative_skips [i];
78375fd0b74Schristos     }
78475fd0b74Schristos 
78575fd0b74Schristos   return offset;
78675fd0b74Schristos }
787