133965Sjdp/* Stabs in sections linking support.
2218822Sdim   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3218822Sdim   2006, 2007 Free Software Foundation, Inc.
433965Sjdp   Written by Ian Lance Taylor, Cygnus Support.
533965Sjdp
6130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
733965Sjdp
8130561Sobrien   This program is free software; you can redistribute it and/or modify
9130561Sobrien   it under the terms of the GNU General Public License as published by
10130561Sobrien   the Free Software Foundation; either version 2 of the License, or
11130561Sobrien   (at your option) any later version.
1233965Sjdp
13130561Sobrien   This program is distributed in the hope that it will be useful,
14130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130561Sobrien   GNU General Public License for more details.
1733965Sjdp
18130561Sobrien   You should have received a copy of the GNU General Public License
19130561Sobrien   along with this program; if not, write to the Free Software
20218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2133965Sjdp
2233965Sjdp/* This file contains support for linking stabs in sections, as used
2333965Sjdp   on COFF and ELF.  */
2433965Sjdp
25218822Sdim#include "sysdep.h"
2633965Sjdp#include "bfd.h"
2733965Sjdp#include "libbfd.h"
2833965Sjdp#include "aout/stab_gnu.h"
2989857Sobrien#include "safe-ctype.h"
3033965Sjdp
3133965Sjdp/* Stabs entries use a 12 byte format:
3233965Sjdp     4 byte string table index
3333965Sjdp     1 byte stab type
3433965Sjdp     1 byte stab other field
3533965Sjdp     2 byte stab desc field
3633965Sjdp     4 byte stab value
3733965Sjdp   FIXME: This will have to change for a 64 bit object format.
3833965Sjdp
3933965Sjdp   The stabs symbols are divided into compilation units.  For the
4033965Sjdp   first entry in each unit, the type of 0, the value is the length of
4133965Sjdp   the string table for this unit, and the desc field is the number of
4233965Sjdp   stabs symbols for this unit.  */
4333965Sjdp
44218822Sdim#define STRDXOFF  0
45218822Sdim#define TYPEOFF   4
46218822Sdim#define OTHEROFF  5
47218822Sdim#define DESCOFF   6
48218822Sdim#define VALOFF    8
49218822Sdim#define STABSIZE  12
5033965Sjdp
5133965Sjdp/* A linked list of totals that we have found for a particular header
52130561Sobrien   file.  A total is a unique identifier for a particular BINCL...EINCL
53130561Sobrien   sequence of STABs that can be used to identify duplicate sequences.
54130561Sobrien   It consists of three fields, 'sum_chars' which is the sum of all the
55130561Sobrien   STABS characters; 'num_chars' which is the number of these charactes
56130561Sobrien   and 'symb' which is a buffer of all the symbols in the sequence.  This
57130561Sobrien   buffer is only checked as a last resort.  */
5833965Sjdp
5933965Sjdpstruct stab_link_includes_totals
6033965Sjdp{
6133965Sjdp  struct stab_link_includes_totals *next;
62130561Sobrien  bfd_vma sum_chars;  /* Accumulated sum of STABS characters.  */
63130561Sobrien  bfd_vma num_chars;  /* Number of STABS characters.  */
64130561Sobrien  const char* symb;   /* The STABS characters themselves.  */
6533965Sjdp};
6633965Sjdp
6733965Sjdp/* An entry in the header file hash table.  */
6833965Sjdp
6933965Sjdpstruct stab_link_includes_entry
7033965Sjdp{
7133965Sjdp  struct bfd_hash_entry root;
7233965Sjdp  /* List of totals we have found for this file.  */
7333965Sjdp  struct stab_link_includes_totals *totals;
7433965Sjdp};
7533965Sjdp
7633965Sjdp/* This structure is used to hold a list of N_BINCL symbols, some of
7733965Sjdp   which might be converted into N_EXCL symbols.  */
7833965Sjdp
7933965Sjdpstruct stab_excl_list
8033965Sjdp{
8133965Sjdp  /* The next symbol to convert.  */
8233965Sjdp  struct stab_excl_list *next;
8333965Sjdp  /* The offset to this symbol in the section contents.  */
8433965Sjdp  bfd_size_type offset;
8533965Sjdp  /* The value to use for the symbol.  */
8633965Sjdp  bfd_vma val;
8733965Sjdp  /* The type of this symbol (N_BINCL or N_EXCL).  */
8833965Sjdp  int type;
8933965Sjdp};
9033965Sjdp
9133965Sjdp/* This structure is stored with each .stab section.  */
9233965Sjdp
9333965Sjdpstruct stab_section_info
9433965Sjdp{
9533965Sjdp  /* This is a linked list of N_BINCL symbols which should be
9633965Sjdp     converted into N_EXCL symbols.  */
9733965Sjdp  struct stab_excl_list *excls;
9833965Sjdp
9933965Sjdp  /* This is used to map input stab offsets within their sections
10033965Sjdp     to output stab offsets, to take into account stabs that have
10133965Sjdp     been deleted.  If it is NULL, the output offsets are the same
10233965Sjdp     as the input offsets, because no stabs have been deleted from
10333965Sjdp     this section.  Otherwise the i'th entry is the number of
10433965Sjdp     bytes of stabs that have been deleted prior to the i'th
10577298Sobrien     stab.  */
10633965Sjdp  bfd_size_type *cumulative_skips;
10733965Sjdp
10833965Sjdp  /* This is an array of string indices.  For each stab symbol, we
10933965Sjdp     store the string index here.  If a stab symbol should not be
11033965Sjdp     included in the final output, the string index is -1.  */
11133965Sjdp  bfd_size_type stridxs[1];
11233965Sjdp};
11333965Sjdp
11433965Sjdp
11533965Sjdp/* The function to create a new entry in the header file hash table.  */
11633965Sjdp
11733965Sjdpstatic struct bfd_hash_entry *
118218822Sdimstab_link_includes_newfunc (struct bfd_hash_entry *entry,
119218822Sdim			    struct bfd_hash_table *table,
120218822Sdim			    const char *string)
12133965Sjdp{
12233965Sjdp  struct stab_link_includes_entry *ret =
12333965Sjdp    (struct stab_link_includes_entry *) entry;
12433965Sjdp
12533965Sjdp  /* Allocate the structure if it has not already been allocated by a
12633965Sjdp     subclass.  */
127218822Sdim  if (ret == NULL)
128218822Sdim    ret = bfd_hash_allocate (table,
129218822Sdim			     sizeof (struct stab_link_includes_entry));
130218822Sdim  if (ret == NULL)
131218822Sdim    return NULL;
13233965Sjdp
13333965Sjdp  /* Call the allocation method of the superclass.  */
13433965Sjdp  ret = ((struct stab_link_includes_entry *)
13533965Sjdp	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
13633965Sjdp  if (ret)
137218822Sdim    /* Set local fields.  */
138218822Sdim    ret->totals = NULL;
13933965Sjdp
14033965Sjdp  return (struct bfd_hash_entry *) ret;
14133965Sjdp}
14233965Sjdp
14333965Sjdp/* This function is called for each input file from the add_symbols
14433965Sjdp   pass of the linker.  */
14533965Sjdp
146130561Sobrienbfd_boolean
147218822Sdim_bfd_link_section_stabs (bfd *abfd,
148218822Sdim			 struct stab_info *sinfo,
149218822Sdim			 asection *stabsec,
150218822Sdim			 asection *stabstrsec,
151218822Sdim			 void * *psecinfo,
152218822Sdim			 bfd_size_type *pstring_offset)
15333965Sjdp{
154130561Sobrien  bfd_boolean first;
15589857Sobrien  bfd_size_type count, amt;
15633965Sjdp  struct stab_section_info *secinfo;
15733965Sjdp  bfd_byte *stabbuf = NULL;
15833965Sjdp  bfd_byte *stabstrbuf = NULL;
15933965Sjdp  bfd_byte *sym, *symend;
16033965Sjdp  bfd_size_type stroff, next_stroff, skip;
16133965Sjdp  bfd_size_type *pstridx;
16233965Sjdp
163218822Sdim  if (stabsec->size == 0
164218822Sdim      || stabstrsec->size == 0)
165218822Sdim    /* This file does not contain stabs debugging information.  */
166218822Sdim    return TRUE;
16733965Sjdp
168218822Sdim  if (stabsec->size % STABSIZE != 0)
169218822Sdim    /* Something is wrong with the format of these stab symbols.
170218822Sdim       Don't try to optimize them.  */
171218822Sdim    return TRUE;
17233965Sjdp
17333965Sjdp  if ((stabstrsec->flags & SEC_RELOC) != 0)
174218822Sdim    /* We shouldn't see relocations in the strings, and we aren't
175218822Sdim       prepared to handle them.  */
176218822Sdim    return TRUE;
17733965Sjdp
178218822Sdim  if (bfd_is_abs_section (stabsec->output_section)
179218822Sdim      || bfd_is_abs_section (stabstrsec->output_section))
180218822Sdim    /* At least one of the sections is being discarded from the
181218822Sdim       link, so we should just ignore them.  */
182218822Sdim    return TRUE;
18333965Sjdp
184130561Sobrien  first = FALSE;
18533965Sjdp
186218822Sdim  if (sinfo->stabstr == NULL)
18733965Sjdp    {
188218822Sdim      flagword flags;
189218822Sdim
19033965Sjdp      /* Initialize the stabs information we need to keep track of.  */
191130561Sobrien      first = TRUE;
19233965Sjdp      sinfo->strings = _bfd_stringtab_init ();
19333965Sjdp      if (sinfo->strings == NULL)
19433965Sjdp	goto error_return;
19560484Sobrien      /* Make sure the first byte is zero.  */
196130561Sobrien      (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
197218822Sdim      if (! bfd_hash_table_init (&sinfo->includes,
198218822Sdim				 stab_link_includes_newfunc,
199218822Sdim				 sizeof (struct stab_link_includes_entry)))
20033965Sjdp	goto error_return;
201218822Sdim      flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
202218822Sdim	       | SEC_LINKER_CREATED);
203218822Sdim      sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
204218822Sdim							   flags);
205218822Sdim      if (sinfo->stabstr == NULL)
206218822Sdim	goto error_return;
20733965Sjdp    }
20833965Sjdp
20933965Sjdp  /* Initialize the information we are going to store for this .stab
21033965Sjdp     section.  */
211218822Sdim  count = stabsec->size / STABSIZE;
21233965Sjdp
21389857Sobrien  amt = sizeof (struct stab_section_info);
21489857Sobrien  amt += (count - 1) * sizeof (bfd_size_type);
21589857Sobrien  *psecinfo = bfd_alloc (abfd, amt);
21633965Sjdp  if (*psecinfo == NULL)
21733965Sjdp    goto error_return;
21833965Sjdp
21933965Sjdp  secinfo = (struct stab_section_info *) *psecinfo;
22033965Sjdp  secinfo->excls = NULL;
221218822Sdim  stabsec->rawsize = stabsec->size;
22233965Sjdp  secinfo->cumulative_skips = NULL;
22389857Sobrien  memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
22433965Sjdp
22533965Sjdp  /* Read the stabs information from abfd.  */
226218822Sdim  if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
227218822Sdim      || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
22833965Sjdp    goto error_return;
22933965Sjdp
23033965Sjdp  /* Look through the stabs symbols, work out the new string indices,
23133965Sjdp     and identify N_BINCL symbols which can be eliminated.  */
23233965Sjdp  stroff = 0;
233130561Sobrien  /* The stabs sections can be split when
234130561Sobrien     -split-by-reloc/-split-by-file is used.  We must keep track of
235130561Sobrien     each stab section's place in the single concatenated string
236130561Sobrien     table.  */
237130561Sobrien  next_stroff = pstring_offset ? *pstring_offset : 0;
23833965Sjdp  skip = 0;
23933965Sjdp
240218822Sdim  symend = stabbuf + stabsec->size;
24133965Sjdp  for (sym = stabbuf, pstridx = secinfo->stridxs;
24233965Sjdp       sym < symend;
24333965Sjdp       sym += STABSIZE, ++pstridx)
24433965Sjdp    {
245104834Sobrien      bfd_size_type symstroff;
24633965Sjdp      int type;
24733965Sjdp      const char *string;
24833965Sjdp
24933965Sjdp      if (*pstridx != 0)
250218822Sdim	/* This symbol has already been handled by an N_BINCL pass.  */
251218822Sdim	continue;
25233965Sjdp
25333965Sjdp      type = sym[TYPEOFF];
25433965Sjdp
25533965Sjdp      if (type == 0)
25633965Sjdp	{
25733965Sjdp	  /* Special type 0 stabs indicate the offset to the next
258130561Sobrien	     string table.  We only copy the very first one.  */
25933965Sjdp	  stroff = next_stroff;
26033965Sjdp	  next_stroff += bfd_get_32 (abfd, sym + 8);
261130561Sobrien	  if (pstring_offset)
262130561Sobrien	    *pstring_offset = next_stroff;
26333965Sjdp	  if (! first)
26433965Sjdp	    {
26533965Sjdp	      *pstridx = (bfd_size_type) -1;
26633965Sjdp	      ++skip;
26733965Sjdp	      continue;
26833965Sjdp	    }
269130561Sobrien	  first = FALSE;
27033965Sjdp	}
27133965Sjdp
27233965Sjdp      /* Store the string in the hash table, and record the index.  */
273104834Sobrien      symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
274218822Sdim      if (symstroff >= stabstrsec->size)
275104834Sobrien	{
276104834Sobrien	  (*_bfd_error_handler)
277218822Sdim	    (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
278218822Sdim	     abfd, stabsec, (long) (sym - stabbuf));
279104834Sobrien	  bfd_set_error (bfd_error_bad_value);
280104834Sobrien	  goto error_return;
281104834Sobrien	}
282104834Sobrien      string = (char *) stabstrbuf + symstroff;
283130561Sobrien      *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
28433965Sjdp
28533965Sjdp      /* An N_BINCL symbol indicates the start of the stabs entries
28633965Sjdp	 for a header file.  We need to scan ahead to the next N_EINCL
28733965Sjdp	 symbol, ignoring nesting, adding up all the characters in the
28833965Sjdp	 symbol names, not including the file numbers in types (the
28933965Sjdp	 first number after an open parenthesis).  */
290107492Sobrien      if (type == (int) N_BINCL)
29133965Sjdp	{
292130561Sobrien	  bfd_vma sum_chars;
293130561Sobrien	  bfd_vma num_chars;
294130561Sobrien	  bfd_vma buf_len = 0;
295130561Sobrien	  char * symb;
296130561Sobrien	  char * symb_rover;
29733965Sjdp	  int nest;
298130561Sobrien	  bfd_byte * incl_sym;
299130561Sobrien	  struct stab_link_includes_entry * incl_entry;
300130561Sobrien	  struct stab_link_includes_totals * t;
301130561Sobrien	  struct stab_excl_list * ne;
30233965Sjdp
303130561Sobrien	  symb = symb_rover = NULL;
304130561Sobrien	  sum_chars = num_chars = 0;
30533965Sjdp	  nest = 0;
306130561Sobrien
30733965Sjdp	  for (incl_sym = sym + STABSIZE;
30833965Sjdp	       incl_sym < symend;
30933965Sjdp	       incl_sym += STABSIZE)
31033965Sjdp	    {
31133965Sjdp	      int incl_type;
31233965Sjdp
31333965Sjdp	      incl_type = incl_sym[TYPEOFF];
31433965Sjdp	      if (incl_type == 0)
31533965Sjdp		break;
316130561Sobrien	      else if (incl_type == (int) N_EXCL)
317130561Sobrien		continue;
318107492Sobrien	      else if (incl_type == (int) N_EINCL)
31933965Sjdp		{
32033965Sjdp		  if (nest == 0)
32133965Sjdp		    break;
32233965Sjdp		  --nest;
32333965Sjdp		}
324107492Sobrien	      else if (incl_type == (int) N_BINCL)
32533965Sjdp		++nest;
32633965Sjdp	      else if (nest == 0)
32733965Sjdp		{
32833965Sjdp		  const char *str;
32933965Sjdp
33033965Sjdp		  str = ((char *) stabstrbuf
33133965Sjdp			 + stroff
33233965Sjdp			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
33333965Sjdp		  for (; *str != '\0'; str++)
33433965Sjdp		    {
335130561Sobrien		      if (num_chars >= buf_len)
336130561Sobrien			{
337130561Sobrien			  buf_len += 32 * 1024;
338130561Sobrien			  symb = bfd_realloc (symb, buf_len);
339130561Sobrien			  if (symb == NULL)
340130561Sobrien			    goto error_return;
341130561Sobrien			  symb_rover = symb + num_chars;
342130561Sobrien			}
343130561Sobrien		      * symb_rover ++ = * str;
344130561Sobrien		      sum_chars += *str;
345130561Sobrien		      num_chars ++;
34633965Sjdp		      if (*str == '(')
34733965Sjdp			{
34833965Sjdp			  /* Skip the file number.  */
34933965Sjdp			  ++str;
35089857Sobrien			  while (ISDIGIT (*str))
35133965Sjdp			    ++str;
35233965Sjdp			  --str;
35333965Sjdp			}
35433965Sjdp		    }
35533965Sjdp		}
35633965Sjdp	    }
35733965Sjdp
358130561Sobrien	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
359130561Sobrien
36033965Sjdp	  /* If we have already included a header file with the same
36133965Sjdp	     value, then replaced this one with an N_EXCL symbol.  */
362218822Sdim	  incl_entry = (struct stab_link_includes_entry * )
363218822Sdim	    bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
36433965Sjdp	  if (incl_entry == NULL)
36533965Sjdp	    goto error_return;
36633965Sjdp
36733965Sjdp	  for (t = incl_entry->totals; t != NULL; t = t->next)
368130561Sobrien	    if (t->sum_chars == sum_chars
369130561Sobrien		&& t->num_chars == num_chars
370130561Sobrien		&& memcmp (t->symb, symb, num_chars) == 0)
37133965Sjdp	      break;
37233965Sjdp
37333965Sjdp	  /* Record this symbol, so that we can set the value
374130561Sobrien	     correctly.  */
37589857Sobrien	  amt = sizeof *ne;
376218822Sdim	  ne = bfd_alloc (abfd, amt);
37733965Sjdp	  if (ne == NULL)
37833965Sjdp	    goto error_return;
37933965Sjdp	  ne->offset = sym - stabbuf;
380130561Sobrien	  ne->val = sum_chars;
381107492Sobrien	  ne->type = (int) N_BINCL;
38233965Sjdp	  ne->next = secinfo->excls;
38333965Sjdp	  secinfo->excls = ne;
38433965Sjdp
38533965Sjdp	  if (t == NULL)
38633965Sjdp	    {
38733965Sjdp	      /* This is the first time we have seen this header file
38833965Sjdp		 with this set of stabs strings.  */
389218822Sdim	      t = bfd_hash_allocate (&sinfo->includes, sizeof *t);
39033965Sjdp	      if (t == NULL)
39133965Sjdp		goto error_return;
392130561Sobrien	      t->sum_chars = sum_chars;
393130561Sobrien	      t->num_chars = num_chars;
394130561Sobrien	      t->symb = bfd_realloc (symb, num_chars); /* Trim data down.  */
39533965Sjdp	      t->next = incl_entry->totals;
39633965Sjdp	      incl_entry->totals = t;
39733965Sjdp	    }
39833965Sjdp	  else
39933965Sjdp	    {
40033965Sjdp	      bfd_size_type *incl_pstridx;
40133965Sjdp
40233965Sjdp	      /* We have seen this header file before.  Tell the final
40333965Sjdp		 pass to change the type to N_EXCL.  */
404107492Sobrien	      ne->type = (int) N_EXCL;
40533965Sjdp
406130561Sobrien	      /* Free off superfluous symbols.  */
407130561Sobrien	      free (symb);
408130561Sobrien
40933965Sjdp	      /* Mark the skipped symbols.  */
41033965Sjdp
41133965Sjdp	      nest = 0;
41233965Sjdp	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
41333965Sjdp		   incl_sym < symend;
41433965Sjdp		   incl_sym += STABSIZE, ++incl_pstridx)
41533965Sjdp		{
41633965Sjdp		  int incl_type;
41733965Sjdp
41833965Sjdp		  incl_type = incl_sym[TYPEOFF];
41933965Sjdp
420107492Sobrien		  if (incl_type == (int) N_EINCL)
42133965Sjdp		    {
42233965Sjdp		      if (nest == 0)
42333965Sjdp			{
42433965Sjdp			  *incl_pstridx = (bfd_size_type) -1;
42533965Sjdp			  ++skip;
42633965Sjdp			  break;
42733965Sjdp			}
42833965Sjdp		      --nest;
42933965Sjdp		    }
430107492Sobrien		  else if (incl_type == (int) N_BINCL)
43133965Sjdp		    ++nest;
432130561Sobrien		  else if (incl_type == (int) N_EXCL)
433130561Sobrien		    /* Keep existing exclusion marks.  */
434218822Sdim		    continue;
43533965Sjdp		  else if (nest == 0)
43633965Sjdp		    {
43733965Sjdp		      *incl_pstridx = (bfd_size_type) -1;
43833965Sjdp		      ++skip;
43933965Sjdp		    }
44033965Sjdp		}
44133965Sjdp	    }
44233965Sjdp	}
44333965Sjdp    }
44433965Sjdp
44533965Sjdp  free (stabbuf);
44633965Sjdp  stabbuf = NULL;
44733965Sjdp  free (stabstrbuf);
44833965Sjdp  stabstrbuf = NULL;
44933965Sjdp
45033965Sjdp  /* We need to set the section sizes such that the linker will
45133965Sjdp     compute the output section sizes correctly.  We set the .stab
45233965Sjdp     size to not include the entries we don't want.  We set
45333965Sjdp     SEC_EXCLUDE for the .stabstr section, so that it will be dropped
45433965Sjdp     from the link.  We record the size of the strtab in the first
45533965Sjdp     .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
45633965Sjdp     for that section.  */
457218822Sdim  stabsec->size = (count - skip) * STABSIZE;
458218822Sdim  if (stabsec->size == 0)
459218822Sdim    stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
460218822Sdim  stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
461218822Sdim  sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
46233965Sjdp
46333965Sjdp  /* Calculate the `cumulative_skips' array now that stabs have been
46477298Sobrien     deleted for this section.  */
46533965Sjdp
46633965Sjdp  if (skip != 0)
46733965Sjdp    {
46833965Sjdp      bfd_size_type i, offset;
46933965Sjdp      bfd_size_type *pskips;
47033965Sjdp
47189857Sobrien      amt = count * sizeof (bfd_size_type);
472218822Sdim      secinfo->cumulative_skips = bfd_alloc (abfd, amt);
47333965Sjdp      if (secinfo->cumulative_skips == NULL)
47433965Sjdp	goto error_return;
47533965Sjdp
47633965Sjdp      pskips = secinfo->cumulative_skips;
47733965Sjdp      pstridx = secinfo->stridxs;
47833965Sjdp      offset = 0;
47933965Sjdp
48033965Sjdp      for (i = 0; i < count; i++, pskips++, pstridx++)
48133965Sjdp	{
48233965Sjdp	  *pskips = offset;
48333965Sjdp	  if (*pstridx == (bfd_size_type) -1)
48433965Sjdp	    offset += STABSIZE;
48533965Sjdp	}
48633965Sjdp
48733965Sjdp      BFD_ASSERT (offset != 0);
48833965Sjdp    }
48933965Sjdp
490130561Sobrien  return TRUE;
49133965Sjdp
49233965Sjdp error_return:
49333965Sjdp  if (stabbuf != NULL)
49433965Sjdp    free (stabbuf);
49533965Sjdp  if (stabstrbuf != NULL)
49633965Sjdp    free (stabstrbuf);
497130561Sobrien  return FALSE;
49833965Sjdp}
49989857Sobrien
50089857Sobrien/* This function is called for each input file before the stab
50189857Sobrien   section is relocated.  It discards stab entries for discarded
502130561Sobrien   functions and variables.  The function returns TRUE iff
50389857Sobrien   any entries have been deleted.
50489857Sobrien*/
50589857Sobrien
506130561Sobrienbfd_boolean
507218822Sdim_bfd_discard_section_stabs (bfd *abfd,
508218822Sdim			    asection *stabsec,
509218822Sdim			    void * psecinfo,
510218822Sdim			    bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
511218822Sdim			    void * cookie)
51289857Sobrien{
51389857Sobrien  bfd_size_type count, amt;
51489857Sobrien  struct stab_section_info *secinfo;
51589857Sobrien  bfd_byte *stabbuf = NULL;
51689857Sobrien  bfd_byte *sym, *symend;
51789857Sobrien  bfd_size_type skip;
51889857Sobrien  bfd_size_type *pstridx;
51989857Sobrien  int deleting;
52089857Sobrien
521218822Sdim  if (stabsec->size == 0)
522218822Sdim    /* This file does not contain stabs debugging information.  */
523218822Sdim    return FALSE;
52489857Sobrien
525218822Sdim  if (stabsec->size % STABSIZE != 0)
526218822Sdim    /* Something is wrong with the format of these stab symbols.
527218822Sdim       Don't try to optimize them.  */
528218822Sdim    return FALSE;
52989857Sobrien
53089857Sobrien  if ((stabsec->output_section != NULL
53189857Sobrien       && bfd_is_abs_section (stabsec->output_section)))
532218822Sdim    /* At least one of the sections is being discarded from the
533218822Sdim       link, so we should just ignore them.  */
534218822Sdim    return FALSE;
53589857Sobrien
53689857Sobrien  /* We should have initialized our data in _bfd_link_stab_sections.
53789857Sobrien     If there was some bizarre error reading the string sections, though,
53889857Sobrien     we might not have.  Bail rather than asserting.  */
53989857Sobrien  if (psecinfo == NULL)
540130561Sobrien    return FALSE;
54189857Sobrien
542218822Sdim  count = stabsec->rawsize / STABSIZE;
54389857Sobrien  secinfo = (struct stab_section_info *) psecinfo;
54489857Sobrien
54589857Sobrien  /* Read the stabs information from abfd.  */
546218822Sdim  if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
54789857Sobrien    goto error_return;
54889857Sobrien
54989857Sobrien  /* Look through the stabs symbols and discard any information for
55089857Sobrien     discarded functions.  */
55189857Sobrien  skip = 0;
55289857Sobrien  deleting = -1;
55389857Sobrien
554218822Sdim  symend = stabbuf + stabsec->rawsize;
55589857Sobrien  for (sym = stabbuf, pstridx = secinfo->stridxs;
55689857Sobrien       sym < symend;
55789857Sobrien       sym += STABSIZE, ++pstridx)
55889857Sobrien    {
55989857Sobrien      int type;
56089857Sobrien
56189857Sobrien      if (*pstridx == (bfd_size_type) -1)
562218822Sdim	/* This stab was deleted in a previous pass.  */
563218822Sdim	continue;
56489857Sobrien
56589857Sobrien      type = sym[TYPEOFF];
56689857Sobrien
567107492Sobrien      if (type == (int) N_FUN)
56889857Sobrien	{
56989857Sobrien	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
57089857Sobrien
57189857Sobrien	  if (strx == 0)
57289857Sobrien	    {
57389857Sobrien	      if (deleting)
57489857Sobrien		{
57589857Sobrien		  skip++;
57689857Sobrien		  *pstridx = -1;
57789857Sobrien		}
57889857Sobrien	      deleting = -1;
57989857Sobrien	      continue;
58089857Sobrien	    }
58189857Sobrien	  deleting = 0;
58289857Sobrien	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
58389857Sobrien	    deleting = 1;
58489857Sobrien	}
58589857Sobrien
58689857Sobrien      if (deleting == 1)
58789857Sobrien	{
58889857Sobrien	  *pstridx = -1;
58989857Sobrien	  skip++;
59089857Sobrien	}
59189857Sobrien      else if (deleting == -1)
59289857Sobrien	{
59389857Sobrien	  /* Outside of a function.  Check for deleted variables.  */
594107492Sobrien	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
59589857Sobrien	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
59689857Sobrien	      {
59789857Sobrien		*pstridx = -1;
59889857Sobrien		skip ++;
59989857Sobrien	      }
60089857Sobrien	  /* We should also check for N_GSYM entries which reference a
60189857Sobrien	     deleted global, but those are less harmful to debuggers
60289857Sobrien	     and would require parsing the stab strings.  */
60389857Sobrien	}
60489857Sobrien    }
60589857Sobrien
60689857Sobrien  free (stabbuf);
60789857Sobrien  stabbuf = NULL;
60889857Sobrien
60989857Sobrien  /* Shrink the stabsec as needed.  */
610218822Sdim  stabsec->size -= skip * STABSIZE;
611218822Sdim  if (stabsec->size == 0)
612218822Sdim    stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
61389857Sobrien
61489857Sobrien  /* Recalculate the `cumulative_skips' array now that stabs have been
61589857Sobrien     deleted for this section.  */
61689857Sobrien
61789857Sobrien  if (skip != 0)
61889857Sobrien    {
61989857Sobrien      bfd_size_type i, offset;
62089857Sobrien      bfd_size_type *pskips;
62189857Sobrien
62289857Sobrien      if (secinfo->cumulative_skips == NULL)
62389857Sobrien	{
62489857Sobrien	  amt = count * sizeof (bfd_size_type);
625218822Sdim	  secinfo->cumulative_skips = bfd_alloc (abfd, amt);
62689857Sobrien	  if (secinfo->cumulative_skips == NULL)
62789857Sobrien	    goto error_return;
62889857Sobrien	}
62989857Sobrien
63089857Sobrien      pskips = secinfo->cumulative_skips;
63189857Sobrien      pstridx = secinfo->stridxs;
63289857Sobrien      offset = 0;
63389857Sobrien
63489857Sobrien      for (i = 0; i < count; i++, pskips++, pstridx++)
63589857Sobrien	{
63689857Sobrien	  *pskips = offset;
63789857Sobrien	  if (*pstridx == (bfd_size_type) -1)
63889857Sobrien	    offset += STABSIZE;
63989857Sobrien	}
64089857Sobrien
64189857Sobrien      BFD_ASSERT (offset != 0);
64289857Sobrien    }
64389857Sobrien
644130561Sobrien  return skip > 0;
64589857Sobrien
64689857Sobrien error_return:
64789857Sobrien  if (stabbuf != NULL)
64889857Sobrien    free (stabbuf);
649130561Sobrien  return FALSE;
65089857Sobrien}
65189857Sobrien
65233965Sjdp/* Write out the stab section.  This is called with the relocated
65333965Sjdp   contents.  */
65433965Sjdp
655130561Sobrienbfd_boolean
656218822Sdim_bfd_write_section_stabs (bfd *output_bfd,
657218822Sdim			  struct stab_info *sinfo,
658218822Sdim			  asection *stabsec,
659218822Sdim			  void * *psecinfo,
660218822Sdim			  bfd_byte *contents)
66133965Sjdp{
66233965Sjdp  struct stab_section_info *secinfo;
66333965Sjdp  struct stab_excl_list *e;
66433965Sjdp  bfd_byte *sym, *tosym, *symend;
66533965Sjdp  bfd_size_type *pstridx;
66633965Sjdp
66733965Sjdp  secinfo = (struct stab_section_info *) *psecinfo;
66833965Sjdp
66933965Sjdp  if (secinfo == NULL)
67033965Sjdp    return bfd_set_section_contents (output_bfd, stabsec->output_section,
671218822Sdim				     contents, stabsec->output_offset,
672218822Sdim				     stabsec->size);
67333965Sjdp
67433965Sjdp  /* Handle each N_BINCL entry.  */
67533965Sjdp  for (e = secinfo->excls; e != NULL; e = e->next)
67633965Sjdp    {
67733965Sjdp      bfd_byte *excl_sym;
67833965Sjdp
679218822Sdim      BFD_ASSERT (e->offset < stabsec->rawsize);
68033965Sjdp      excl_sym = contents + e->offset;
68133965Sjdp      bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
68233965Sjdp      excl_sym[TYPEOFF] = e->type;
68333965Sjdp    }
68433965Sjdp
68533965Sjdp  /* Copy over all the stabs symbols, omitting the ones we don't want,
68633965Sjdp     and correcting the string indices for those we do want.  */
68733965Sjdp  tosym = contents;
688218822Sdim  symend = contents + stabsec->rawsize;
68933965Sjdp  for (sym = contents, pstridx = secinfo->stridxs;
69033965Sjdp       sym < symend;
69133965Sjdp       sym += STABSIZE, ++pstridx)
69233965Sjdp    {
69333965Sjdp      if (*pstridx != (bfd_size_type) -1)
69433965Sjdp	{
69533965Sjdp	  if (tosym != sym)
69633965Sjdp	    memcpy (tosym, sym, STABSIZE);
69733965Sjdp	  bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
69833965Sjdp
69933965Sjdp	  if (sym[TYPEOFF] == 0)
70033965Sjdp	    {
70133965Sjdp	      /* This is the header symbol for the stabs section.  We
702130561Sobrien		 don't really need one, since we have merged all the
703130561Sobrien		 input stabs sections into one, but we generate one
704130561Sobrien		 for the benefit of readers which expect to see one.  */
70533965Sjdp	      BFD_ASSERT (sym == contents);
70633965Sjdp	      bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
70733965Sjdp			  tosym + VALOFF);
70833965Sjdp	      bfd_put_16 (output_bfd,
709218822Sdim			  stabsec->output_section->size / STABSIZE - 1,
71033965Sjdp			  tosym + DESCOFF);
71133965Sjdp	    }
71233965Sjdp
71333965Sjdp	  tosym += STABSIZE;
71433965Sjdp	}
71533965Sjdp    }
71633965Sjdp
717218822Sdim  BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
71833965Sjdp
71933965Sjdp  return bfd_set_section_contents (output_bfd, stabsec->output_section,
72089857Sobrien				   contents, (file_ptr) stabsec->output_offset,
721218822Sdim				   stabsec->size);
72233965Sjdp}
72333965Sjdp
72433965Sjdp/* Write out the .stabstr section.  */
72533965Sjdp
726130561Sobrienbfd_boolean
727218822Sdim_bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
72833965Sjdp{
729218822Sdim  if (bfd_is_abs_section (sinfo->stabstr->output_section))
730218822Sdim    /* The section was discarded from the link.  */
731130561Sobrien    return TRUE;
73233965Sjdp
73333965Sjdp  BFD_ASSERT ((sinfo->stabstr->output_offset
73433965Sjdp	       + _bfd_stringtab_size (sinfo->strings))
735218822Sdim	      <= sinfo->stabstr->output_section->size);
73633965Sjdp
73733965Sjdp  if (bfd_seek (output_bfd,
73889857Sobrien		(file_ptr) (sinfo->stabstr->output_section->filepos
73989857Sobrien			    + sinfo->stabstr->output_offset),
74033965Sjdp		SEEK_SET) != 0)
741130561Sobrien    return FALSE;
74233965Sjdp
74333965Sjdp  if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
744130561Sobrien    return FALSE;
74533965Sjdp
74633965Sjdp  /* We no longer need the stabs information.  */
74733965Sjdp  _bfd_stringtab_free (sinfo->strings);
748218822Sdim  bfd_hash_table_free (&sinfo->includes);
74933965Sjdp
750130561Sobrien  return TRUE;
75133965Sjdp}
75233965Sjdp
75333965Sjdp/* Adjust an address in the .stab section.  Given OFFSET within
75433965Sjdp   STABSEC, this returns the new offset in the adjusted stab section,
75533965Sjdp   or -1 if the address refers to a stab which has been removed.  */
75633965Sjdp
75733965Sjdpbfd_vma
758218822Sdim_bfd_stab_section_offset (asection *stabsec,
759218822Sdim			  void * psecinfo,
760218822Sdim			  bfd_vma offset)
76133965Sjdp{
76233965Sjdp  struct stab_section_info *secinfo;
76333965Sjdp
764218822Sdim  secinfo = (struct stab_section_info *) psecinfo;
76533965Sjdp
76633965Sjdp  if (secinfo == NULL)
76733965Sjdp    return offset;
76833965Sjdp
769218822Sdim  if (offset >= stabsec->rawsize)
770218822Sdim    return offset - stabsec->rawsize + stabsec->size;
77133965Sjdp
77233965Sjdp  if (secinfo->cumulative_skips)
77333965Sjdp    {
77433965Sjdp      bfd_vma i;
77533965Sjdp
77633965Sjdp      i = offset / STABSIZE;
77733965Sjdp
77833965Sjdp      if (secinfo->stridxs [i] == (bfd_size_type) -1)
77933965Sjdp	return (bfd_vma) -1;
78033965Sjdp
78133965Sjdp      return offset - secinfo->cumulative_skips [i];
78233965Sjdp    }
78333965Sjdp
78433965Sjdp  return offset;
78533965Sjdp}
786