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