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