stabs.c revision 1.1.1.1.2.1 1 1.1 christos /* Stabs in sections linking support.
2 1.1.1.1.2.1 pgoyette Copyright (C) 1996-2015 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.1 christos
116 1.1 christos /* The function to create a new entry in the header file hash table. */
118 1.1 christos
119 1.1 christos static struct bfd_hash_entry *
120 1.1 christos stab_link_includes_newfunc (struct bfd_hash_entry *entry,
121 1.1 christos struct bfd_hash_table *table,
122 1.1 christos const char *string)
123 1.1 christos {
124 1.1 christos struct stab_link_includes_entry *ret =
125 1.1 christos (struct stab_link_includes_entry *) entry;
126 1.1 christos
127 1.1 christos /* Allocate the structure if it has not already been allocated by a
128 1.1 christos subclass. */
129 1.1 christos if (ret == NULL)
130 1.1 christos ret = (struct stab_link_includes_entry *)
131 1.1 christos bfd_hash_allocate (table, sizeof (struct stab_link_includes_entry));
132 1.1 christos if (ret == NULL)
133 1.1 christos return NULL;
134 1.1 christos
135 1.1 christos /* Call the allocation method of the superclass. */
136 1.1 christos ret = ((struct stab_link_includes_entry *)
137 1.1 christos bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
138 1.1 christos if (ret)
139 1.1 christos /* Set local fields. */
140 1.1 christos ret->totals = NULL;
141 1.1 christos
142 1.1 christos return (struct bfd_hash_entry *) ret;
143 1.1 christos }
144 1.1 christos
145 1.1 christos /* This function is called for each input file from the add_symbols
147 1.1 christos pass of the linker. */
148 1.1 christos
149 1.1 christos bfd_boolean
150 1.1 christos _bfd_link_section_stabs (bfd *abfd,
151 1.1 christos struct stab_info *sinfo,
152 1.1 christos asection *stabsec,
153 1.1 christos asection *stabstrsec,
154 1.1 christos void * *psecinfo,
155 1.1 christos bfd_size_type *pstring_offset)
156 1.1 christos {
157 1.1 christos bfd_boolean first;
158 1.1 christos bfd_size_type count, amt;
159 1.1 christos struct stab_section_info *secinfo;
160 1.1 christos bfd_byte *stabbuf = NULL;
161 1.1 christos bfd_byte *stabstrbuf = NULL;
162 1.1 christos bfd_byte *sym, *symend;
163 1.1 christos bfd_size_type stroff, next_stroff, skip;
164 1.1 christos bfd_size_type *pstridx;
165 1.1 christos
166 1.1 christos if (stabsec->size == 0
167 1.1 christos || stabstrsec->size == 0)
168 1.1 christos /* This file does not contain stabs debugging information. */
169 1.1 christos return TRUE;
170 1.1 christos
171 1.1 christos if (stabsec->size % STABSIZE != 0)
172 1.1 christos /* Something is wrong with the format of these stab symbols.
173 1.1 christos Don't try to optimize them. */
174 1.1 christos return TRUE;
175 1.1 christos
176 1.1 christos if ((stabstrsec->flags & SEC_RELOC) != 0)
177 1.1 christos /* We shouldn't see relocations in the strings, and we aren't
178 1.1 christos prepared to handle them. */
179 1.1 christos return TRUE;
180 1.1 christos
181 1.1 christos if (bfd_is_abs_section (stabsec->output_section)
182 1.1 christos || bfd_is_abs_section (stabstrsec->output_section))
183 1.1 christos /* At least one of the sections is being discarded from the
184 1.1 christos link, so we should just ignore them. */
185 1.1 christos return TRUE;
186 1.1 christos
187 1.1 christos first = FALSE;
188 1.1 christos
189 1.1 christos if (sinfo->stabstr == NULL)
190 1.1 christos {
191 1.1 christos flagword flags;
192 1.1 christos
193 1.1 christos /* Initialize the stabs information we need to keep track of. */
194 1.1 christos first = TRUE;
195 1.1 christos sinfo->strings = _bfd_stringtab_init ();
196 1.1 christos if (sinfo->strings == NULL)
197 1.1 christos goto error_return;
198 1.1 christos /* Make sure the first byte is zero. */
199 1.1 christos (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
200 1.1 christos if (! bfd_hash_table_init (&sinfo->includes,
201 1.1 christos stab_link_includes_newfunc,
202 1.1 christos sizeof (struct stab_link_includes_entry)))
203 1.1 christos goto error_return;
204 1.1 christos flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
205 1.1 christos | SEC_LINKER_CREATED);
206 1.1 christos sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
207 1.1 christos flags);
208 1.1 christos if (sinfo->stabstr == NULL)
209 1.1 christos goto error_return;
210 1.1 christos }
211 1.1 christos
212 1.1 christos /* Initialize the information we are going to store for this .stab
213 1.1 christos section. */
214 1.1 christos count = stabsec->size / STABSIZE;
215 1.1 christos
216 1.1 christos amt = sizeof (struct stab_section_info);
217 1.1 christos amt += (count - 1) * sizeof (bfd_size_type);
218 1.1 christos *psecinfo = bfd_alloc (abfd, amt);
219 1.1 christos if (*psecinfo == NULL)
220 1.1 christos goto error_return;
221 1.1 christos
222 1.1 christos secinfo = (struct stab_section_info *) *psecinfo;
223 1.1 christos secinfo->excls = NULL;
224 1.1 christos stabsec->rawsize = stabsec->size;
225 1.1 christos secinfo->cumulative_skips = NULL;
226 1.1 christos memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
227 1.1 christos
228 1.1 christos /* Read the stabs information from abfd. */
229 1.1 christos if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
230 1.1 christos || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
231 1.1 christos goto error_return;
232 1.1 christos
233 1.1 christos /* Look through the stabs symbols, work out the new string indices,
234 1.1 christos and identify N_BINCL symbols which can be eliminated. */
235 1.1 christos stroff = 0;
236 1.1 christos /* The stabs sections can be split when
237 1.1 christos -split-by-reloc/-split-by-file is used. We must keep track of
238 1.1 christos each stab section's place in the single concatenated string
239 1.1 christos table. */
240 1.1 christos next_stroff = pstring_offset ? *pstring_offset : 0;
241 1.1 christos skip = 0;
242 1.1 christos
243 1.1 christos symend = stabbuf + stabsec->size;
244 1.1 christos for (sym = stabbuf, pstridx = secinfo->stridxs;
245 1.1 christos sym < symend;
246 1.1 christos sym += STABSIZE, ++pstridx)
247 1.1 christos {
248 1.1 christos bfd_size_type symstroff;
249 1.1 christos int type;
250 1.1 christos const char *string;
251 1.1 christos
252 1.1 christos if (*pstridx != 0)
253 1.1 christos /* This symbol has already been handled by an N_BINCL pass. */
254 1.1 christos continue;
255 1.1 christos
256 1.1 christos type = sym[TYPEOFF];
257 1.1 christos
258 1.1 christos if (type == 0)
259 1.1 christos {
260 1.1 christos /* Special type 0 stabs indicate the offset to the next
261 1.1 christos string table. We only copy the very first one. */
262 1.1 christos stroff = next_stroff;
263 1.1 christos next_stroff += bfd_get_32 (abfd, sym + 8);
264 1.1 christos if (pstring_offset)
265 1.1 christos *pstring_offset = next_stroff;
266 1.1 christos if (! first)
267 1.1 christos {
268 1.1 christos *pstridx = (bfd_size_type) -1;
269 1.1 christos ++skip;
270 1.1 christos continue;
271 1.1 christos }
272 1.1 christos first = FALSE;
273 1.1 christos }
274 1.1 christos
275 1.1 christos /* Store the string in the hash table, and record the index. */
276 1.1 christos symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
277 1.1 christos if (symstroff >= stabstrsec->size)
278 1.1 christos {
279 1.1 christos (*_bfd_error_handler)
280 1.1 christos (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
281 1.1 christos abfd, stabsec, (long) (sym - stabbuf));
282 1.1 christos bfd_set_error (bfd_error_bad_value);
283 1.1 christos goto error_return;
284 1.1 christos }
285 1.1 christos string = (char *) stabstrbuf + symstroff;
286 1.1 christos *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
287 1.1 christos
288 1.1 christos /* An N_BINCL symbol indicates the start of the stabs entries
289 1.1 christos for a header file. We need to scan ahead to the next N_EINCL
290 1.1 christos symbol, ignoring nesting, adding up all the characters in the
291 1.1 christos symbol names, not including the file numbers in types (the
292 1.1 christos first number after an open parenthesis). */
293 1.1 christos if (type == (int) N_BINCL)
294 1.1 christos {
295 1.1 christos bfd_vma sum_chars;
296 1.1 christos bfd_vma num_chars;
297 1.1 christos bfd_vma buf_len = 0;
298 1.1 christos char * symb;
299 1.1 christos char * symb_rover;
300 1.1 christos int nest;
301 1.1 christos bfd_byte * incl_sym;
302 1.1 christos struct stab_link_includes_entry * incl_entry;
303 1.1 christos struct stab_link_includes_totals * t;
304 1.1 christos struct stab_excl_list * ne;
305 1.1 christos
306 1.1 christos symb = symb_rover = NULL;
307 1.1 christos sum_chars = num_chars = 0;
308 1.1 christos nest = 0;
309 1.1 christos
310 1.1 christos for (incl_sym = sym + STABSIZE;
311 1.1 christos incl_sym < symend;
312 1.1 christos incl_sym += STABSIZE)
313 1.1 christos {
314 1.1 christos int incl_type;
315 1.1 christos
316 1.1 christos incl_type = incl_sym[TYPEOFF];
317 1.1 christos if (incl_type == 0)
318 1.1 christos break;
319 1.1 christos else if (incl_type == (int) N_EXCL)
320 1.1 christos continue;
321 1.1 christos else if (incl_type == (int) N_EINCL)
322 1.1 christos {
323 1.1 christos if (nest == 0)
324 1.1 christos break;
325 1.1 christos --nest;
326 1.1 christos }
327 1.1 christos else if (incl_type == (int) N_BINCL)
328 1.1 christos ++nest;
329 1.1 christos else if (nest == 0)
330 1.1 christos {
331 1.1 christos const char *str;
332 1.1 christos
333 1.1 christos str = ((char *) stabstrbuf
334 1.1 christos + stroff
335 1.1 christos + bfd_get_32 (abfd, incl_sym + STRDXOFF));
336 1.1 christos for (; *str != '\0'; str++)
337 1.1 christos {
338 1.1 christos if (num_chars >= buf_len)
339 1.1 christos {
340 1.1 christos buf_len += 32 * 1024;
341 1.1 christos symb = (char *) bfd_realloc_or_free (symb, buf_len);
342 1.1 christos if (symb == NULL)
343 1.1 christos goto error_return;
344 1.1 christos symb_rover = symb + num_chars;
345 1.1 christos }
346 1.1 christos * symb_rover ++ = * str;
347 1.1 christos sum_chars += *str;
348 1.1 christos num_chars ++;
349 1.1 christos if (*str == '(')
350 1.1 christos {
351 1.1 christos /* Skip the file number. */
352 1.1 christos ++str;
353 1.1 christos while (ISDIGIT (*str))
354 1.1 christos ++str;
355 1.1 christos --str;
356 1.1 christos }
357 1.1 christos }
358 1.1 christos }
359 1.1 christos }
360 1.1 christos
361 1.1 christos BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
362 1.1 christos
363 1.1 christos /* If we have already included a header file with the same
364 1.1 christos value, then replaced this one with an N_EXCL symbol. */
365 1.1 christos incl_entry = (struct stab_link_includes_entry * )
366 1.1 christos bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
367 1.1 christos if (incl_entry == NULL)
368 1.1 christos goto error_return;
369 1.1 christos
370 1.1 christos for (t = incl_entry->totals; t != NULL; t = t->next)
371 1.1 christos if (t->sum_chars == sum_chars
372 1.1 christos && t->num_chars == num_chars
373 1.1 christos && memcmp (t->symb, symb, num_chars) == 0)
374 1.1 christos break;
375 1.1 christos
376 1.1 christos /* Record this symbol, so that we can set the value
377 1.1 christos correctly. */
378 1.1 christos amt = sizeof *ne;
379 1.1 christos ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
380 1.1 christos if (ne == NULL)
381 1.1 christos goto error_return;
382 1.1 christos ne->offset = sym - stabbuf;
383 1.1 christos ne->val = sum_chars;
384 1.1 christos ne->type = (int) N_BINCL;
385 1.1 christos ne->next = secinfo->excls;
386 1.1 christos secinfo->excls = ne;
387 1.1 christos
388 1.1 christos if (t == NULL)
389 1.1 christos {
390 1.1 christos /* This is the first time we have seen this header file
391 1.1 christos with this set of stabs strings. */
392 1.1 christos t = (struct stab_link_includes_totals *)
393 1.1 christos bfd_hash_allocate (&sinfo->includes, sizeof *t);
394 1.1 christos if (t == NULL)
395 1.1 christos goto error_return;
396 1.1 christos t->sum_chars = sum_chars;
397 1.1 christos t->num_chars = num_chars;
398 1.1 christos /* Trim data down. */
399 1.1 christos t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
400 1.1 christos t->next = incl_entry->totals;
401 1.1 christos incl_entry->totals = t;
402 1.1 christos }
403 1.1 christos else
404 1.1 christos {
405 1.1 christos bfd_size_type *incl_pstridx;
406 1.1 christos
407 1.1 christos /* We have seen this header file before. Tell the final
408 1.1 christos pass to change the type to N_EXCL. */
409 1.1 christos ne->type = (int) N_EXCL;
410 1.1 christos
411 1.1 christos /* Free off superfluous symbols. */
412 1.1 christos free (symb);
413 1.1 christos
414 1.1 christos /* Mark the skipped symbols. */
415 1.1 christos
416 1.1 christos nest = 0;
417 1.1 christos for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
418 1.1 christos incl_sym < symend;
419 1.1 christos incl_sym += STABSIZE, ++incl_pstridx)
420 1.1 christos {
421 1.1 christos int incl_type;
422 1.1 christos
423 1.1 christos incl_type = incl_sym[TYPEOFF];
424 1.1 christos
425 1.1 christos if (incl_type == (int) N_EINCL)
426 1.1 christos {
427 1.1 christos if (nest == 0)
428 1.1 christos {
429 1.1 christos *incl_pstridx = (bfd_size_type) -1;
430 1.1 christos ++skip;
431 1.1 christos break;
432 1.1 christos }
433 1.1 christos --nest;
434 1.1 christos }
435 1.1 christos else if (incl_type == (int) N_BINCL)
436 1.1 christos ++nest;
437 1.1 christos else if (incl_type == (int) N_EXCL)
438 1.1 christos /* Keep existing exclusion marks. */
439 1.1 christos continue;
440 1.1 christos else if (nest == 0)
441 1.1 christos {
442 1.1 christos *incl_pstridx = (bfd_size_type) -1;
443 1.1 christos ++skip;
444 1.1 christos }
445 1.1 christos }
446 1.1 christos }
447 1.1 christos }
448 1.1 christos }
449 1.1 christos
450 1.1 christos free (stabbuf);
451 1.1 christos stabbuf = NULL;
452 1.1 christos free (stabstrbuf);
453 1.1 christos stabstrbuf = NULL;
454 1.1 christos
455 1.1 christos /* We need to set the section sizes such that the linker will
456 1.1 christos compute the output section sizes correctly. We set the .stab
457 1.1 christos size to not include the entries we don't want. We set
458 1.1 christos SEC_EXCLUDE for the .stabstr section, so that it will be dropped
459 1.1 christos from the link. We record the size of the strtab in the first
460 1.1 christos .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
461 1.1 christos for that section. */
462 1.1 christos stabsec->size = (count - skip) * STABSIZE;
463 1.1 christos if (stabsec->size == 0)
464 1.1 christos stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
465 1.1 christos stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
466 1.1 christos sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
467 1.1 christos
468 1.1 christos /* Calculate the `cumulative_skips' array now that stabs have been
469 1.1 christos deleted for this section. */
470 1.1 christos
471 1.1 christos if (skip != 0)
472 1.1 christos {
473 1.1 christos bfd_size_type i, offset;
474 1.1 christos bfd_size_type *pskips;
475 1.1 christos
476 1.1 christos amt = count * sizeof (bfd_size_type);
477 1.1 christos secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
478 1.1 christos if (secinfo->cumulative_skips == NULL)
479 1.1 christos goto error_return;
480 1.1 christos
481 1.1 christos pskips = secinfo->cumulative_skips;
482 1.1 christos pstridx = secinfo->stridxs;
483 1.1 christos offset = 0;
484 1.1 christos
485 1.1 christos for (i = 0; i < count; i++, pskips++, pstridx++)
486 1.1 christos {
487 1.1 christos *pskips = offset;
488 1.1 christos if (*pstridx == (bfd_size_type) -1)
489 1.1 christos offset += STABSIZE;
490 1.1 christos }
491 1.1 christos
492 1.1 christos BFD_ASSERT (offset != 0);
493 1.1 christos }
494 1.1 christos
495 1.1 christos return TRUE;
496 1.1 christos
497 1.1 christos error_return:
498 1.1 christos if (stabbuf != NULL)
499 1.1 christos free (stabbuf);
500 1.1 christos if (stabstrbuf != NULL)
501 1.1 christos free (stabstrbuf);
502 1.1 christos return FALSE;
503 1.1 christos }
504 1.1 christos
505 1.1 christos /* This function is called for each input file before the stab
507 1.1 christos section is relocated. It discards stab entries for discarded
508 1.1 christos functions and variables. The function returns TRUE iff
509 1.1 christos any entries have been deleted.
510 1.1 christos */
511 1.1 christos
512 1.1 christos bfd_boolean
513 1.1 christos _bfd_discard_section_stabs (bfd *abfd,
514 1.1 christos asection *stabsec,
515 1.1 christos void * psecinfo,
516 1.1 christos bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
517 1.1 christos void * cookie)
518 1.1 christos {
519 1.1 christos bfd_size_type count, amt;
520 1.1 christos struct stab_section_info *secinfo;
521 1.1 christos bfd_byte *stabbuf = NULL;
522 1.1 christos bfd_byte *sym, *symend;
523 1.1 christos bfd_size_type skip;
524 1.1 christos bfd_size_type *pstridx;
525 1.1 christos int deleting;
526 1.1 christos
527 1.1 christos if (stabsec->size == 0)
528 1.1 christos /* This file does not contain stabs debugging information. */
529 1.1 christos return FALSE;
530 1.1 christos
531 1.1 christos if (stabsec->size % STABSIZE != 0)
532 1.1 christos /* Something is wrong with the format of these stab symbols.
533 1.1 christos Don't try to optimize them. */
534 1.1 christos return FALSE;
535 1.1 christos
536 1.1 christos if ((stabsec->output_section != NULL
537 1.1 christos && bfd_is_abs_section (stabsec->output_section)))
538 1.1 christos /* At least one of the sections is being discarded from the
539 1.1.1.1.2.1 pgoyette link, so we should just ignore them. */
540 1.1 christos return FALSE;
541 1.1 christos
542 1.1 christos /* We should have initialized our data in _bfd_link_section_stabs.
543 1.1 christos If there was some bizarre error reading the string sections, though,
544 1.1 christos we might not have. Bail rather than asserting. */
545 1.1 christos if (psecinfo == NULL)
546 1.1 christos return FALSE;
547 1.1 christos
548 1.1 christos count = stabsec->rawsize / STABSIZE;
549 1.1 christos secinfo = (struct stab_section_info *) psecinfo;
550 1.1 christos
551 1.1 christos /* Read the stabs information from abfd. */
552 1.1 christos if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
553 1.1 christos goto error_return;
554 1.1 christos
555 1.1 christos /* Look through the stabs symbols and discard any information for
556 1.1 christos discarded functions. */
557 1.1 christos skip = 0;
558 1.1 christos deleting = -1;
559 1.1 christos
560 1.1 christos symend = stabbuf + stabsec->rawsize;
561 1.1 christos for (sym = stabbuf, pstridx = secinfo->stridxs;
562 1.1 christos sym < symend;
563 1.1 christos sym += STABSIZE, ++pstridx)
564 1.1 christos {
565 1.1 christos int type;
566 1.1 christos
567 1.1 christos if (*pstridx == (bfd_size_type) -1)
568 1.1 christos /* This stab was deleted in a previous pass. */
569 1.1 christos continue;
570 1.1 christos
571 1.1 christos type = sym[TYPEOFF];
572 1.1 christos
573 1.1 christos if (type == (int) N_FUN)
574 1.1 christos {
575 1.1 christos int strx = bfd_get_32 (abfd, sym + STRDXOFF);
576 1.1 christos
577 1.1 christos if (strx == 0)
578 1.1 christos {
579 1.1 christos if (deleting)
580 1.1 christos {
581 1.1 christos skip++;
582 1.1 christos *pstridx = -1;
583 1.1 christos }
584 1.1 christos deleting = -1;
585 1.1 christos continue;
586 1.1 christos }
587 1.1 christos deleting = 0;
588 1.1 christos if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
589 1.1 christos deleting = 1;
590 1.1 christos }
591 1.1 christos
592 1.1 christos if (deleting == 1)
593 1.1 christos {
594 1.1 christos *pstridx = -1;
595 1.1 christos skip++;
596 1.1 christos }
597 1.1 christos else if (deleting == -1)
598 1.1 christos {
599 1.1 christos /* Outside of a function. Check for deleted variables. */
600 1.1 christos if (type == (int) N_STSYM || type == (int) N_LCSYM)
601 1.1 christos if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
602 1.1 christos {
603 1.1 christos *pstridx = -1;
604 1.1 christos skip ++;
605 1.1 christos }
606 1.1 christos /* We should also check for N_GSYM entries which reference a
607 1.1 christos deleted global, but those are less harmful to debuggers
608 1.1 christos and would require parsing the stab strings. */
609 1.1 christos }
610 1.1 christos }
611 1.1 christos
612 1.1 christos free (stabbuf);
613 1.1 christos stabbuf = NULL;
614 1.1 christos
615 1.1 christos /* Shrink the stabsec as needed. */
616 1.1 christos stabsec->size -= skip * STABSIZE;
617 1.1 christos if (stabsec->size == 0)
618 1.1 christos stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
619 1.1 christos
620 1.1 christos /* Recalculate the `cumulative_skips' array now that stabs have been
621 1.1 christos deleted for this section. */
622 1.1 christos
623 1.1 christos if (skip != 0)
624 1.1 christos {
625 1.1 christos bfd_size_type i, offset;
626 1.1 christos bfd_size_type *pskips;
627 1.1 christos
628 1.1 christos if (secinfo->cumulative_skips == NULL)
629 1.1 christos {
630 1.1 christos amt = count * sizeof (bfd_size_type);
631 1.1 christos secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
632 1.1 christos if (secinfo->cumulative_skips == NULL)
633 1.1 christos goto error_return;
634 1.1 christos }
635 1.1 christos
636 1.1 christos pskips = secinfo->cumulative_skips;
637 1.1 christos pstridx = secinfo->stridxs;
638 1.1 christos offset = 0;
639 1.1 christos
640 1.1 christos for (i = 0; i < count; i++, pskips++, pstridx++)
641 1.1 christos {
642 1.1 christos *pskips = offset;
643 1.1 christos if (*pstridx == (bfd_size_type) -1)
644 1.1 christos offset += STABSIZE;
645 1.1 christos }
646 1.1 christos
647 1.1 christos BFD_ASSERT (offset != 0);
648 1.1 christos }
649 1.1 christos
650 1.1 christos return skip > 0;
651 1.1 christos
652 1.1 christos error_return:
653 1.1 christos if (stabbuf != NULL)
654 1.1 christos free (stabbuf);
655 1.1 christos return FALSE;
656 1.1 christos }
657 1.1 christos
658 1.1 christos /* Write out the stab section. This is called with the relocated
659 1.1 christos contents. */
660 1.1 christos
661 1.1 christos bfd_boolean
662 1.1 christos _bfd_write_section_stabs (bfd *output_bfd,
663 1.1 christos struct stab_info *sinfo,
664 1.1 christos asection *stabsec,
665 1.1 christos void * *psecinfo,
666 1.1 christos bfd_byte *contents)
667 1.1 christos {
668 1.1 christos struct stab_section_info *secinfo;
669 1.1 christos struct stab_excl_list *e;
670 1.1 christos bfd_byte *sym, *tosym, *symend;
671 1.1 christos bfd_size_type *pstridx;
672 1.1 christos
673 1.1 christos secinfo = (struct stab_section_info *) *psecinfo;
674 1.1 christos
675 1.1 christos if (secinfo == NULL)
676 1.1 christos return bfd_set_section_contents (output_bfd, stabsec->output_section,
677 1.1 christos contents, stabsec->output_offset,
678 1.1 christos stabsec->size);
679 1.1 christos
680 1.1 christos /* Handle each N_BINCL entry. */
681 1.1 christos for (e = secinfo->excls; e != NULL; e = e->next)
682 1.1 christos {
683 1.1 christos bfd_byte *excl_sym;
684 1.1 christos
685 1.1 christos BFD_ASSERT (e->offset < stabsec->rawsize);
686 1.1 christos excl_sym = contents + e->offset;
687 1.1 christos bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
688 1.1 christos excl_sym[TYPEOFF] = e->type;
689 1.1 christos }
690 1.1 christos
691 1.1 christos /* Copy over all the stabs symbols, omitting the ones we don't want,
692 1.1 christos and correcting the string indices for those we do want. */
693 1.1 christos tosym = contents;
694 1.1 christos symend = contents + stabsec->rawsize;
695 1.1 christos for (sym = contents, pstridx = secinfo->stridxs;
696 1.1 christos sym < symend;
697 1.1 christos sym += STABSIZE, ++pstridx)
698 1.1 christos {
699 1.1 christos if (*pstridx != (bfd_size_type) -1)
700 1.1 christos {
701 1.1 christos if (tosym != sym)
702 1.1 christos memcpy (tosym, sym, STABSIZE);
703 1.1 christos bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
704 1.1 christos
705 1.1 christos if (sym[TYPEOFF] == 0)
706 1.1 christos {
707 1.1 christos /* This is the header symbol for the stabs section. We
708 1.1 christos don't really need one, since we have merged all the
709 1.1 christos input stabs sections into one, but we generate one
710 1.1 christos for the benefit of readers which expect to see one. */
711 1.1 christos BFD_ASSERT (sym == contents);
712 1.1 christos bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
713 1.1 christos tosym + VALOFF);
714 1.1 christos bfd_put_16 (output_bfd,
715 1.1 christos stabsec->output_section->size / STABSIZE - 1,
716 1.1 christos tosym + DESCOFF);
717 1.1 christos }
718 1.1 christos
719 1.1 christos tosym += STABSIZE;
720 1.1 christos }
721 1.1 christos }
722 1.1 christos
723 1.1 christos BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
724 1.1 christos
725 1.1 christos return bfd_set_section_contents (output_bfd, stabsec->output_section,
726 1.1 christos contents, (file_ptr) stabsec->output_offset,
727 1.1 christos stabsec->size);
728 1.1 christos }
729 1.1 christos
730 1.1 christos /* Write out the .stabstr section. */
731 1.1 christos
732 1.1 christos bfd_boolean
733 1.1 christos _bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
734 1.1 christos {
735 1.1 christos if (bfd_is_abs_section (sinfo->stabstr->output_section))
736 1.1 christos /* The section was discarded from the link. */
737 1.1 christos return TRUE;
738 1.1 christos
739 1.1 christos BFD_ASSERT ((sinfo->stabstr->output_offset
740 1.1 christos + _bfd_stringtab_size (sinfo->strings))
741 1.1 christos <= sinfo->stabstr->output_section->size);
742 1.1 christos
743 1.1 christos if (bfd_seek (output_bfd,
744 1.1 christos (file_ptr) (sinfo->stabstr->output_section->filepos
745 1.1 christos + sinfo->stabstr->output_offset),
746 1.1 christos SEEK_SET) != 0)
747 1.1 christos return FALSE;
748 1.1 christos
749 1.1 christos if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
750 1.1 christos return FALSE;
751 1.1 christos
752 1.1 christos /* We no longer need the stabs information. */
753 1.1 christos _bfd_stringtab_free (sinfo->strings);
754 1.1 christos bfd_hash_table_free (&sinfo->includes);
755 1.1 christos
756 1.1 christos return TRUE;
757 1.1 christos }
758 1.1 christos
759 1.1 christos /* Adjust an address in the .stab section. Given OFFSET within
760 1.1 christos STABSEC, this returns the new offset in the adjusted stab section,
761 1.1 christos or -1 if the address refers to a stab which has been removed. */
762 1.1 christos
763 1.1 christos bfd_vma
764 1.1 christos _bfd_stab_section_offset (asection *stabsec,
765 1.1 christos void * psecinfo,
766 1.1 christos bfd_vma offset)
767 1.1 christos {
768 1.1 christos struct stab_section_info *secinfo;
769 1.1 christos
770 1.1 christos secinfo = (struct stab_section_info *) psecinfo;
771 1.1 christos
772 1.1 christos if (secinfo == NULL)
773 1.1 christos return offset;
774 1.1 christos
775 1.1 christos if (offset >= stabsec->rawsize)
776 1.1 christos return offset - stabsec->rawsize + stabsec->size;
777 1.1 christos
778 1.1 christos if (secinfo->cumulative_skips)
779 1.1 christos {
780 1.1 christos bfd_vma i;
781 1.1 christos
782 1.1 christos i = offset / STABSIZE;
783 1.1 christos
784 1.1 christos if (secinfo->stridxs [i] == (bfd_size_type) -1)
785 1.1 christos return (bfd_vma) -1;
786 1.1 christos
787 1.1 christos return offset - secinfo->cumulative_skips [i];
788 1.1 christos }
789
790 return offset;
791 }
792