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