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