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