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