1 |
/* Stabs in sections linking support. |
/* Stabs in sections linking support. |
2 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
Written by Ian Lance Taylor, Cygnus Support. |
Written by Ian Lance Taylor, Cygnus Support. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
7 |
|
|
8 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
9 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
10 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
11 |
(at your option) any later version. |
(at your option) any later version. |
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
GNU General Public License for more details. |
GNU General Public License for more details. |
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
19 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
20 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 |
|
|
22 |
/* This file contains support for linking stabs in sections, as used |
/* This file contains support for linking stabs in sections, as used |
23 |
on COFF and ELF. */ |
on COFF and ELF. */ |
48 |
#define VALOFF (8) |
#define VALOFF (8) |
49 |
#define STABSIZE (12) |
#define STABSIZE (12) |
50 |
|
|
|
/* A hash table used for header files with N_BINCL entries. */ |
|
|
|
|
|
struct stab_link_includes_table |
|
|
{ |
|
|
struct bfd_hash_table root; |
|
|
}; |
|
|
|
|
51 |
/* A linked list of totals that we have found for a particular header |
/* A linked list of totals that we have found for a particular header |
52 |
file. */ |
file. A total is a unique identifier for a particular BINCL...EINCL |
53 |
|
sequence of STABs that can be used to identify duplicate sequences. |
54 |
|
It consists of three fields, 'sum_chars' which is the sum of all the |
55 |
|
STABS characters; 'num_chars' which is the number of these charactes |
56 |
|
and 'symb' which is a buffer of all the symbols in the sequence. This |
57 |
|
buffer is only checked as a last resort. */ |
58 |
|
|
59 |
struct stab_link_includes_totals |
struct stab_link_includes_totals |
60 |
{ |
{ |
61 |
struct stab_link_includes_totals *next; |
struct stab_link_includes_totals *next; |
62 |
bfd_vma total; |
bfd_vma sum_chars; /* Accumulated sum of STABS characters. */ |
63 |
|
bfd_vma num_chars; /* Number of STABS characters. */ |
64 |
|
const char* symb; /* The STABS characters themselves. */ |
65 |
}; |
}; |
66 |
|
|
67 |
/* An entry in the header file hash table. */ |
/* An entry in the header file hash table. */ |
73 |
struct stab_link_includes_totals *totals; |
struct stab_link_includes_totals *totals; |
74 |
}; |
}; |
75 |
|
|
|
/* Look up an entry in an the header file hash table. */ |
|
|
|
|
|
#define stab_link_includes_lookup(table, string, create, copy) \ |
|
|
((struct stab_link_includes_entry *) \ |
|
|
bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
|
|
|
|
76 |
/* This structure is used to hold a list of N_BINCL symbols, some of |
/* This structure is used to hold a list of N_BINCL symbols, some of |
77 |
which might be converted into N_EXCL symbols. */ |
which might be converted into N_EXCL symbols. */ |
78 |
|
|
111 |
bfd_size_type stridxs[1]; |
bfd_size_type stridxs[1]; |
112 |
}; |
}; |
113 |
|
|
|
/* This structure is used to keep track of stabs in sections |
|
|
information while linking. */ |
|
|
|
|
|
struct stab_info |
|
|
{ |
|
|
/* A hash table used to hold stabs strings. */ |
|
|
struct bfd_strtab_hash *strings; |
|
|
/* The header file hash table. */ |
|
|
struct stab_link_includes_table includes; |
|
|
/* The first .stabstr section. */ |
|
|
asection *stabstr; |
|
|
}; |
|
|
|
|
114 |
static struct bfd_hash_entry *stab_link_includes_newfunc |
static struct bfd_hash_entry *stab_link_includes_newfunc |
115 |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
116 |
|
|
149 |
/* This function is called for each input file from the add_symbols |
/* This function is called for each input file from the add_symbols |
150 |
pass of the linker. */ |
pass of the linker. */ |
151 |
|
|
152 |
boolean |
bfd_boolean |
153 |
_bfd_link_section_stabs (abfd, psinfo, stabsec, stabstrsec, psecinfo) |
_bfd_link_section_stabs (abfd, sinfo, stabsec, stabstrsec, psecinfo, pstring_offset) |
154 |
bfd *abfd; |
bfd *abfd; |
155 |
PTR *psinfo; |
struct stab_info *sinfo; |
156 |
asection *stabsec; |
asection *stabsec; |
157 |
asection *stabstrsec; |
asection *stabstrsec; |
158 |
PTR *psecinfo; |
PTR *psecinfo; |
159 |
|
bfd_size_type *pstring_offset; |
160 |
{ |
{ |
161 |
boolean first; |
bfd_boolean first; |
|
struct stab_info *sinfo; |
|
162 |
bfd_size_type count, amt; |
bfd_size_type count, amt; |
163 |
struct stab_section_info *secinfo; |
struct stab_section_info *secinfo; |
164 |
bfd_byte *stabbuf = NULL; |
bfd_byte *stabbuf = NULL; |
167 |
bfd_size_type stroff, next_stroff, skip; |
bfd_size_type stroff, next_stroff, skip; |
168 |
bfd_size_type *pstridx; |
bfd_size_type *pstridx; |
169 |
|
|
170 |
if (stabsec->_raw_size == 0 |
if (stabsec->size == 0 |
171 |
|| stabstrsec->_raw_size == 0) |
|| stabstrsec->size == 0) |
172 |
{ |
{ |
173 |
/* This file does not contain stabs debugging information. */ |
/* This file does not contain stabs debugging information. */ |
174 |
return true; |
return TRUE; |
175 |
} |
} |
176 |
|
|
177 |
if (stabsec->_raw_size % STABSIZE != 0) |
if (stabsec->size % STABSIZE != 0) |
178 |
{ |
{ |
179 |
/* Something is wrong with the format of these stab symbols. |
/* Something is wrong with the format of these stab symbols. |
180 |
Don't try to optimize them. */ |
Don't try to optimize them. */ |
181 |
return true; |
return TRUE; |
182 |
} |
} |
183 |
|
|
184 |
if ((stabstrsec->flags & SEC_RELOC) != 0) |
if ((stabstrsec->flags & SEC_RELOC) != 0) |
185 |
{ |
{ |
186 |
/* We shouldn't see relocations in the strings, and we aren't |
/* We shouldn't see relocations in the strings, and we aren't |
187 |
prepared to handle them. */ |
prepared to handle them. */ |
188 |
return true; |
return TRUE; |
189 |
} |
} |
190 |
|
|
191 |
if ((stabsec->output_section != NULL |
if ((stabsec->output_section != NULL |
194 |
&& bfd_is_abs_section (stabstrsec->output_section))) |
&& bfd_is_abs_section (stabstrsec->output_section))) |
195 |
{ |
{ |
196 |
/* At least one of the sections is being discarded from the |
/* At least one of the sections is being discarded from the |
197 |
link, so we should just ignore them. */ |
link, so we should just ignore them. */ |
198 |
return true; |
return TRUE; |
199 |
} |
} |
200 |
|
|
201 |
first = false; |
first = FALSE; |
202 |
|
|
203 |
if (*psinfo == NULL) |
if (sinfo->stabstr == NULL) |
204 |
{ |
{ |
205 |
/* Initialize the stabs information we need to keep track of. */ |
/* Initialize the stabs information we need to keep track of. */ |
206 |
first = true; |
first = TRUE; |
|
amt = sizeof (struct stab_info); |
|
|
*psinfo = (PTR) bfd_alloc (abfd, amt); |
|
|
if (*psinfo == NULL) |
|
|
goto error_return; |
|
|
sinfo = (struct stab_info *) *psinfo; |
|
207 |
sinfo->strings = _bfd_stringtab_init (); |
sinfo->strings = _bfd_stringtab_init (); |
208 |
if (sinfo->strings == NULL) |
if (sinfo->strings == NULL) |
209 |
goto error_return; |
goto error_return; |
210 |
/* Make sure the first byte is zero. */ |
/* Make sure the first byte is zero. */ |
211 |
(void) _bfd_stringtab_add (sinfo->strings, "", true, true); |
(void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE); |
212 |
if (! bfd_hash_table_init_n (&sinfo->includes.root, |
if (! bfd_hash_table_init_n (&sinfo->includes, |
213 |
stab_link_includes_newfunc, |
stab_link_includes_newfunc, |
214 |
251)) |
251)) |
215 |
goto error_return; |
goto error_return; |
216 |
sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr"); |
sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr"); |
217 |
sinfo->stabstr->flags |= SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING; |
if (sinfo->stabstr == NULL) |
218 |
|
goto error_return; |
219 |
|
sinfo->stabstr->flags |= (SEC_HAS_CONTENTS | SEC_READONLY |
220 |
|
| SEC_DEBUGGING | SEC_LINKER_CREATED); |
221 |
} |
} |
222 |
|
|
|
sinfo = (struct stab_info *) *psinfo; |
|
|
|
|
223 |
/* Initialize the information we are going to store for this .stab |
/* Initialize the information we are going to store for this .stab |
224 |
section. */ |
section. */ |
225 |
|
|
226 |
count = stabsec->_raw_size / STABSIZE; |
count = stabsec->size / STABSIZE; |
227 |
|
|
228 |
amt = sizeof (struct stab_section_info); |
amt = sizeof (struct stab_section_info); |
229 |
amt += (count - 1) * sizeof (bfd_size_type); |
amt += (count - 1) * sizeof (bfd_size_type); |
233 |
|
|
234 |
secinfo = (struct stab_section_info *) *psecinfo; |
secinfo = (struct stab_section_info *) *psecinfo; |
235 |
secinfo->excls = NULL; |
secinfo->excls = NULL; |
236 |
|
stabsec->rawsize = stabsec->size; |
237 |
secinfo->cumulative_skips = NULL; |
secinfo->cumulative_skips = NULL; |
238 |
memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type)); |
memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type)); |
239 |
|
|
240 |
/* Read the stabs information from abfd. */ |
/* Read the stabs information from abfd. */ |
241 |
|
|
242 |
stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size); |
if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf) |
243 |
stabstrbuf = (bfd_byte *) bfd_malloc (stabstrsec->_raw_size); |
|| !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf)) |
|
if (stabbuf == NULL || stabstrbuf == NULL) |
|
|
goto error_return; |
|
|
|
|
|
if (! bfd_get_section_contents (abfd, stabsec, stabbuf, (bfd_vma) 0, |
|
|
stabsec->_raw_size) |
|
|
|| ! bfd_get_section_contents (abfd, stabstrsec, stabstrbuf, (bfd_vma) 0, |
|
|
stabstrsec->_raw_size)) |
|
244 |
goto error_return; |
goto error_return; |
245 |
|
|
246 |
/* Look through the stabs symbols, work out the new string indices, |
/* Look through the stabs symbols, work out the new string indices, |
247 |
and identify N_BINCL symbols which can be eliminated. */ |
and identify N_BINCL symbols which can be eliminated. */ |
248 |
|
|
249 |
stroff = 0; |
stroff = 0; |
250 |
next_stroff = 0; |
/* The stabs sections can be split when |
251 |
|
-split-by-reloc/-split-by-file is used. We must keep track of |
252 |
|
each stab section's place in the single concatenated string |
253 |
|
table. */ |
254 |
|
next_stroff = pstring_offset ? *pstring_offset : 0; |
255 |
skip = 0; |
skip = 0; |
256 |
|
|
257 |
symend = stabbuf + stabsec->_raw_size; |
symend = stabbuf + stabsec->size; |
258 |
for (sym = stabbuf, pstridx = secinfo->stridxs; |
for (sym = stabbuf, pstridx = secinfo->stridxs; |
259 |
sym < symend; |
sym < symend; |
260 |
sym += STABSIZE, ++pstridx) |
sym += STABSIZE, ++pstridx) |
274 |
if (type == 0) |
if (type == 0) |
275 |
{ |
{ |
276 |
/* Special type 0 stabs indicate the offset to the next |
/* Special type 0 stabs indicate the offset to the next |
277 |
string table. We only copy the very first one. */ |
string table. We only copy the very first one. */ |
278 |
stroff = next_stroff; |
stroff = next_stroff; |
279 |
next_stroff += bfd_get_32 (abfd, sym + 8); |
next_stroff += bfd_get_32 (abfd, sym + 8); |
280 |
|
if (pstring_offset) |
281 |
|
*pstring_offset = next_stroff; |
282 |
if (! first) |
if (! first) |
283 |
{ |
{ |
284 |
*pstridx = (bfd_size_type) -1; |
*pstridx = (bfd_size_type) -1; |
285 |
++skip; |
++skip; |
286 |
continue; |
continue; |
287 |
} |
} |
288 |
first = false; |
first = FALSE; |
289 |
} |
} |
290 |
|
|
291 |
/* Store the string in the hash table, and record the index. */ |
/* Store the string in the hash table, and record the index. */ |
292 |
symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF); |
symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF); |
293 |
if (symstroff >= stabstrsec->_raw_size) |
if (symstroff >= stabstrsec->size) |
294 |
{ |
{ |
295 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
296 |
(_("%s(%s+0x%lx): Stabs entry has invalid string index."), |
(_("%B(%A+0x%lx): Stabs entry has invalid string index."), |
297 |
bfd_archive_filename (abfd), |
abfd, stabsec, (long) (sym - stabbuf)); |
|
bfd_get_section_name (abfd, stabsec), |
|
|
(long) (sym - stabbuf)); |
|
298 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
299 |
goto error_return; |
goto error_return; |
300 |
} |
} |
301 |
string = (char *) stabstrbuf + symstroff; |
string = (char *) stabstrbuf + symstroff; |
302 |
*pstridx = _bfd_stringtab_add (sinfo->strings, string, true, true); |
*pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE); |
303 |
|
|
304 |
/* An N_BINCL symbol indicates the start of the stabs entries |
/* An N_BINCL symbol indicates the start of the stabs entries |
305 |
for a header file. We need to scan ahead to the next N_EINCL |
for a header file. We need to scan ahead to the next N_EINCL |
306 |
symbol, ignoring nesting, adding up all the characters in the |
symbol, ignoring nesting, adding up all the characters in the |
307 |
symbol names, not including the file numbers in types (the |
symbol names, not including the file numbers in types (the |
308 |
first number after an open parenthesis). */ |
first number after an open parenthesis). */ |
309 |
if (type == N_BINCL) |
if (type == (int) N_BINCL) |
310 |
{ |
{ |
311 |
bfd_vma val; |
bfd_vma sum_chars; |
312 |
|
bfd_vma num_chars; |
313 |
|
bfd_vma buf_len = 0; |
314 |
|
char * symb; |
315 |
|
char * symb_rover; |
316 |
int nest; |
int nest; |
317 |
bfd_byte *incl_sym; |
bfd_byte * incl_sym; |
318 |
struct stab_link_includes_entry *incl_entry; |
struct stab_link_includes_entry * incl_entry; |
319 |
struct stab_link_includes_totals *t; |
struct stab_link_includes_totals * t; |
320 |
struct stab_excl_list *ne; |
struct stab_excl_list * ne; |
321 |
|
|
322 |
val = 0; |
symb = symb_rover = NULL; |
323 |
|
sum_chars = num_chars = 0; |
324 |
nest = 0; |
nest = 0; |
325 |
|
|
326 |
for (incl_sym = sym + STABSIZE; |
for (incl_sym = sym + STABSIZE; |
327 |
incl_sym < symend; |
incl_sym < symend; |
328 |
incl_sym += STABSIZE) |
incl_sym += STABSIZE) |
332 |
incl_type = incl_sym[TYPEOFF]; |
incl_type = incl_sym[TYPEOFF]; |
333 |
if (incl_type == 0) |
if (incl_type == 0) |
334 |
break; |
break; |
335 |
else if (incl_type == N_EINCL) |
else if (incl_type == (int) N_EXCL) |
336 |
|
continue; |
337 |
|
else if (incl_type == (int) N_EINCL) |
338 |
{ |
{ |
339 |
if (nest == 0) |
if (nest == 0) |
340 |
break; |
break; |
341 |
--nest; |
--nest; |
342 |
} |
} |
343 |
else if (incl_type == N_BINCL) |
else if (incl_type == (int) N_BINCL) |
344 |
++nest; |
++nest; |
345 |
else if (nest == 0) |
else if (nest == 0) |
346 |
{ |
{ |
351 |
+ bfd_get_32 (abfd, incl_sym + STRDXOFF)); |
+ bfd_get_32 (abfd, incl_sym + STRDXOFF)); |
352 |
for (; *str != '\0'; str++) |
for (; *str != '\0'; str++) |
353 |
{ |
{ |
354 |
val += *str; |
if (num_chars >= buf_len) |
355 |
|
{ |
356 |
|
buf_len += 32 * 1024; |
357 |
|
symb = bfd_realloc (symb, buf_len); |
358 |
|
if (symb == NULL) |
359 |
|
goto error_return; |
360 |
|
symb_rover = symb + num_chars; |
361 |
|
} |
362 |
|
* symb_rover ++ = * str; |
363 |
|
sum_chars += *str; |
364 |
|
num_chars ++; |
365 |
if (*str == '(') |
if (*str == '(') |
366 |
{ |
{ |
367 |
/* Skip the file number. */ |
/* Skip the file number. */ |
374 |
} |
} |
375 |
} |
} |
376 |
|
|
377 |
|
BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb)); |
378 |
|
|
379 |
/* If we have already included a header file with the same |
/* If we have already included a header file with the same |
380 |
value, then replaced this one with an N_EXCL symbol. */ |
value, then replaced this one with an N_EXCL symbol. */ |
381 |
incl_entry = stab_link_includes_lookup (&sinfo->includes, string, |
incl_entry = (struct stab_link_includes_entry * ) |
382 |
true, true); |
bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE); |
383 |
if (incl_entry == NULL) |
if (incl_entry == NULL) |
384 |
goto error_return; |
goto error_return; |
385 |
|
|
386 |
for (t = incl_entry->totals; t != NULL; t = t->next) |
for (t = incl_entry->totals; t != NULL; t = t->next) |
387 |
if (t->total == val) |
if (t->sum_chars == sum_chars |
388 |
|
&& t->num_chars == num_chars |
389 |
|
&& memcmp (t->symb, symb, num_chars) == 0) |
390 |
break; |
break; |
391 |
|
|
392 |
/* Record this symbol, so that we can set the value |
/* Record this symbol, so that we can set the value |
393 |
correctly. */ |
correctly. */ |
394 |
amt = sizeof *ne; |
amt = sizeof *ne; |
395 |
ne = (struct stab_excl_list *) bfd_alloc (abfd, amt); |
ne = (struct stab_excl_list *) bfd_alloc (abfd, amt); |
396 |
if (ne == NULL) |
if (ne == NULL) |
397 |
goto error_return; |
goto error_return; |
398 |
ne->offset = sym - stabbuf; |
ne->offset = sym - stabbuf; |
399 |
ne->val = val; |
ne->val = sum_chars; |
400 |
ne->type = N_BINCL; |
ne->type = (int) N_BINCL; |
401 |
ne->next = secinfo->excls; |
ne->next = secinfo->excls; |
402 |
secinfo->excls = ne; |
secinfo->excls = ne; |
403 |
|
|
406 |
/* This is the first time we have seen this header file |
/* This is the first time we have seen this header file |
407 |
with this set of stabs strings. */ |
with this set of stabs strings. */ |
408 |
t = ((struct stab_link_includes_totals *) |
t = ((struct stab_link_includes_totals *) |
409 |
bfd_hash_allocate (&sinfo->includes.root, sizeof *t)); |
bfd_hash_allocate (&sinfo->includes, sizeof *t)); |
410 |
if (t == NULL) |
if (t == NULL) |
411 |
goto error_return; |
goto error_return; |
412 |
t->total = val; |
t->sum_chars = sum_chars; |
413 |
|
t->num_chars = num_chars; |
414 |
|
t->symb = bfd_realloc (symb, num_chars); /* Trim data down. */ |
415 |
t->next = incl_entry->totals; |
t->next = incl_entry->totals; |
416 |
incl_entry->totals = t; |
incl_entry->totals = t; |
417 |
} |
} |
421 |
|
|
422 |
/* We have seen this header file before. Tell the final |
/* We have seen this header file before. Tell the final |
423 |
pass to change the type to N_EXCL. */ |
pass to change the type to N_EXCL. */ |
424 |
ne->type = N_EXCL; |
ne->type = (int) N_EXCL; |
425 |
|
|
426 |
|
/* Free off superfluous symbols. */ |
427 |
|
free (symb); |
428 |
|
|
429 |
/* Mark the skipped symbols. */ |
/* Mark the skipped symbols. */ |
430 |
|
|
437 |
|
|
438 |
incl_type = incl_sym[TYPEOFF]; |
incl_type = incl_sym[TYPEOFF]; |
439 |
|
|
440 |
if (incl_type == N_EINCL) |
if (incl_type == (int) N_EINCL) |
441 |
{ |
{ |
442 |
if (nest == 0) |
if (nest == 0) |
443 |
{ |
{ |
447 |
} |
} |
448 |
--nest; |
--nest; |
449 |
} |
} |
450 |
else if (incl_type == N_BINCL) |
else if (incl_type == (int) N_BINCL) |
451 |
++nest; |
++nest; |
452 |
|
else if (incl_type == (int) N_EXCL) |
453 |
|
/* Keep existing exclusion marks. */ |
454 |
|
continue; |
455 |
else if (nest == 0) |
else if (nest == 0) |
456 |
{ |
{ |
457 |
*incl_pstridx = (bfd_size_type) -1; |
*incl_pstridx = (bfd_size_type) -1; |
474 |
from the link. We record the size of the strtab in the first |
from the link. We record the size of the strtab in the first |
475 |
.stabstr section we saw, and make sure we don't set SEC_EXCLUDE |
.stabstr section we saw, and make sure we don't set SEC_EXCLUDE |
476 |
for that section. */ |
for that section. */ |
477 |
stabsec->_cooked_size = (count - skip) * STABSIZE; |
stabsec->size = (count - skip) * STABSIZE; |
478 |
if (stabsec->_cooked_size == 0) |
if (stabsec->size == 0) |
479 |
stabsec->flags |= SEC_EXCLUDE; |
stabsec->flags |= SEC_EXCLUDE; |
480 |
stabstrsec->flags |= SEC_EXCLUDE; |
stabstrsec->flags |= SEC_EXCLUDE; |
481 |
sinfo->stabstr->_cooked_size = _bfd_stringtab_size (sinfo->strings); |
sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings); |
482 |
|
|
483 |
/* Calculate the `cumulative_skips' array now that stabs have been |
/* Calculate the `cumulative_skips' array now that stabs have been |
484 |
deleted for this section. */ |
deleted for this section. */ |
507 |
BFD_ASSERT (offset != 0); |
BFD_ASSERT (offset != 0); |
508 |
} |
} |
509 |
|
|
510 |
return true; |
return TRUE; |
511 |
|
|
512 |
error_return: |
error_return: |
513 |
if (stabbuf != NULL) |
if (stabbuf != NULL) |
514 |
free (stabbuf); |
free (stabbuf); |
515 |
if (stabstrbuf != NULL) |
if (stabstrbuf != NULL) |
516 |
free (stabstrbuf); |
free (stabstrbuf); |
517 |
return false; |
return FALSE; |
518 |
} |
} |
|
|
|
519 |
|
|
520 |
/* This function is called for each input file before the stab |
/* This function is called for each input file before the stab |
521 |
section is relocated. It discards stab entries for discarded |
section is relocated. It discards stab entries for discarded |
522 |
functions and variables. The function returns true iff |
functions and variables. The function returns TRUE iff |
523 |
any entries have been deleted. |
any entries have been deleted. |
524 |
*/ |
*/ |
525 |
|
|
526 |
boolean |
bfd_boolean |
527 |
_bfd_discard_section_stabs (abfd, stabsec, psecinfo, |
_bfd_discard_section_stabs (abfd, stabsec, psecinfo, |
528 |
reloc_symbol_deleted_p, cookie) |
reloc_symbol_deleted_p, cookie) |
529 |
bfd *abfd; |
bfd *abfd; |
530 |
asection *stabsec; |
asection *stabsec; |
531 |
PTR psecinfo; |
PTR psecinfo; |
532 |
boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR)); |
bfd_boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR)); |
533 |
PTR cookie; |
PTR cookie; |
534 |
{ |
{ |
535 |
bfd_size_type count, amt; |
bfd_size_type count, amt; |
540 |
bfd_size_type *pstridx; |
bfd_size_type *pstridx; |
541 |
int deleting; |
int deleting; |
542 |
|
|
543 |
if (stabsec->_raw_size == 0) |
if (stabsec->size == 0) |
544 |
{ |
{ |
545 |
/* This file does not contain stabs debugging information. */ |
/* This file does not contain stabs debugging information. */ |
546 |
return false; |
return FALSE; |
547 |
} |
} |
548 |
|
|
549 |
if (stabsec->_raw_size % STABSIZE != 0) |
if (stabsec->size % STABSIZE != 0) |
550 |
{ |
{ |
551 |
/* Something is wrong with the format of these stab symbols. |
/* Something is wrong with the format of these stab symbols. |
552 |
Don't try to optimize them. */ |
Don't try to optimize them. */ |
553 |
return false; |
return FALSE; |
554 |
} |
} |
555 |
|
|
556 |
if ((stabsec->output_section != NULL |
if ((stabsec->output_section != NULL |
557 |
&& bfd_is_abs_section (stabsec->output_section))) |
&& bfd_is_abs_section (stabsec->output_section))) |
558 |
{ |
{ |
559 |
/* At least one of the sections is being discarded from the |
/* At least one of the sections is being discarded from the |
560 |
link, so we should just ignore them. */ |
link, so we should just ignore them. */ |
561 |
return false; |
return FALSE; |
562 |
} |
} |
563 |
|
|
564 |
/* We should have initialized our data in _bfd_link_stab_sections. |
/* We should have initialized our data in _bfd_link_stab_sections. |
565 |
If there was some bizarre error reading the string sections, though, |
If there was some bizarre error reading the string sections, though, |
566 |
we might not have. Bail rather than asserting. */ |
we might not have. Bail rather than asserting. */ |
567 |
if (psecinfo == NULL) |
if (psecinfo == NULL) |
568 |
return false; |
return FALSE; |
569 |
|
|
570 |
count = stabsec->_raw_size / STABSIZE; |
count = stabsec->rawsize / STABSIZE; |
571 |
secinfo = (struct stab_section_info *) psecinfo; |
secinfo = (struct stab_section_info *) psecinfo; |
572 |
|
|
573 |
/* Read the stabs information from abfd. */ |
/* Read the stabs information from abfd. */ |
574 |
|
|
575 |
stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size); |
if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)) |
|
if (stabbuf == NULL) |
|
|
goto error_return; |
|
|
|
|
|
if (! bfd_get_section_contents (abfd, stabsec, stabbuf, (bfd_vma) 0, |
|
|
stabsec->_raw_size)) |
|
576 |
goto error_return; |
goto error_return; |
577 |
|
|
578 |
/* Look through the stabs symbols and discard any information for |
/* Look through the stabs symbols and discard any information for |
581 |
skip = 0; |
skip = 0; |
582 |
deleting = -1; |
deleting = -1; |
583 |
|
|
584 |
symend = stabbuf + stabsec->_raw_size; |
symend = stabbuf + stabsec->rawsize; |
585 |
for (sym = stabbuf, pstridx = secinfo->stridxs; |
for (sym = stabbuf, pstridx = secinfo->stridxs; |
586 |
sym < symend; |
sym < symend; |
587 |
sym += STABSIZE, ++pstridx) |
sym += STABSIZE, ++pstridx) |
596 |
|
|
597 |
type = sym[TYPEOFF]; |
type = sym[TYPEOFF]; |
598 |
|
|
599 |
if (type == N_FUN) |
if (type == (int) N_FUN) |
600 |
{ |
{ |
601 |
int strx = bfd_get_32 (abfd, sym + STRDXOFF); |
int strx = bfd_get_32 (abfd, sym + STRDXOFF); |
602 |
|
|
623 |
else if (deleting == -1) |
else if (deleting == -1) |
624 |
{ |
{ |
625 |
/* Outside of a function. Check for deleted variables. */ |
/* Outside of a function. Check for deleted variables. */ |
626 |
if (type == N_STSYM || type == N_LCSYM) |
if (type == (int) N_STSYM || type == (int) N_LCSYM) |
627 |
if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) |
if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) |
628 |
{ |
{ |
629 |
*pstridx = -1; |
*pstridx = -1; |
639 |
stabbuf = NULL; |
stabbuf = NULL; |
640 |
|
|
641 |
/* Shrink the stabsec as needed. */ |
/* Shrink the stabsec as needed. */ |
642 |
stabsec->_cooked_size -= skip * STABSIZE; |
stabsec->size -= skip * STABSIZE; |
643 |
if (stabsec->_cooked_size == 0) |
if (stabsec->size == 0) |
644 |
stabsec->flags |= SEC_EXCLUDE; |
stabsec->flags |= SEC_EXCLUDE; |
645 |
|
|
646 |
/* Recalculate the `cumulative_skips' array now that stabs have been |
/* Recalculate the `cumulative_skips' array now that stabs have been |
673 |
BFD_ASSERT (offset != 0); |
BFD_ASSERT (offset != 0); |
674 |
} |
} |
675 |
|
|
676 |
return (skip > 0); |
return skip > 0; |
677 |
|
|
678 |
error_return: |
error_return: |
679 |
if (stabbuf != NULL) |
if (stabbuf != NULL) |
680 |
free (stabbuf); |
free (stabbuf); |
681 |
return false; |
return FALSE; |
682 |
} |
} |
683 |
|
|
684 |
/* Write out the stab section. This is called with the relocated |
/* Write out the stab section. This is called with the relocated |
685 |
contents. */ |
contents. */ |
686 |
|
|
687 |
boolean |
bfd_boolean |
688 |
_bfd_write_section_stabs (output_bfd, psinfo, stabsec, psecinfo, contents) |
_bfd_write_section_stabs (output_bfd, sinfo, stabsec, psecinfo, contents) |
689 |
bfd *output_bfd; |
bfd *output_bfd; |
690 |
PTR *psinfo; |
struct stab_info *sinfo; |
691 |
asection *stabsec; |
asection *stabsec; |
692 |
PTR *psecinfo; |
PTR *psecinfo; |
693 |
bfd_byte *contents; |
bfd_byte *contents; |
694 |
{ |
{ |
|
struct stab_info *sinfo; |
|
695 |
struct stab_section_info *secinfo; |
struct stab_section_info *secinfo; |
696 |
struct stab_excl_list *e; |
struct stab_excl_list *e; |
697 |
bfd_byte *sym, *tosym, *symend; |
bfd_byte *sym, *tosym, *symend; |
698 |
bfd_size_type *pstridx; |
bfd_size_type *pstridx; |
699 |
|
|
|
sinfo = (struct stab_info *) *psinfo; |
|
700 |
secinfo = (struct stab_section_info *) *psecinfo; |
secinfo = (struct stab_section_info *) *psecinfo; |
701 |
|
|
702 |
if (secinfo == NULL) |
if (secinfo == NULL) |
703 |
return bfd_set_section_contents (output_bfd, stabsec->output_section, |
return bfd_set_section_contents (output_bfd, stabsec->output_section, |
704 |
contents, |
contents, stabsec->output_offset, |
705 |
(file_ptr) stabsec->output_offset, |
stabsec->size); |
|
stabsec->_raw_size); |
|
706 |
|
|
707 |
/* Handle each N_BINCL entry. */ |
/* Handle each N_BINCL entry. */ |
708 |
for (e = secinfo->excls; e != NULL; e = e->next) |
for (e = secinfo->excls; e != NULL; e = e->next) |
709 |
{ |
{ |
710 |
bfd_byte *excl_sym; |
bfd_byte *excl_sym; |
711 |
|
|
712 |
BFD_ASSERT (e->offset < stabsec->_raw_size); |
BFD_ASSERT (e->offset < stabsec->rawsize); |
713 |
excl_sym = contents + e->offset; |
excl_sym = contents + e->offset; |
714 |
bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF); |
bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF); |
715 |
excl_sym[TYPEOFF] = e->type; |
excl_sym[TYPEOFF] = e->type; |
718 |
/* Copy over all the stabs symbols, omitting the ones we don't want, |
/* Copy over all the stabs symbols, omitting the ones we don't want, |
719 |
and correcting the string indices for those we do want. */ |
and correcting the string indices for those we do want. */ |
720 |
tosym = contents; |
tosym = contents; |
721 |
symend = contents + stabsec->_raw_size; |
symend = contents + stabsec->rawsize; |
722 |
for (sym = contents, pstridx = secinfo->stridxs; |
for (sym = contents, pstridx = secinfo->stridxs; |
723 |
sym < symend; |
sym < symend; |
724 |
sym += STABSIZE, ++pstridx) |
sym += STABSIZE, ++pstridx) |
732 |
if (sym[TYPEOFF] == 0) |
if (sym[TYPEOFF] == 0) |
733 |
{ |
{ |
734 |
/* This is the header symbol for the stabs section. We |
/* This is the header symbol for the stabs section. We |
735 |
don't really need one, since we have merged all the |
don't really need one, since we have merged all the |
736 |
input stabs sections into one, but we generate one |
input stabs sections into one, but we generate one |
737 |
for the benefit of readers which expect to see one. */ |
for the benefit of readers which expect to see one. */ |
738 |
BFD_ASSERT (sym == contents); |
BFD_ASSERT (sym == contents); |
739 |
bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings), |
bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings), |
740 |
tosym + VALOFF); |
tosym + VALOFF); |
741 |
bfd_put_16 (output_bfd, |
bfd_put_16 (output_bfd, |
742 |
stabsec->output_section->_raw_size / STABSIZE - 1, |
stabsec->output_section->size / STABSIZE - 1, |
743 |
tosym + DESCOFF); |
tosym + DESCOFF); |
744 |
} |
} |
745 |
|
|
747 |
} |
} |
748 |
} |
} |
749 |
|
|
750 |
BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->_cooked_size); |
BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size); |
751 |
|
|
752 |
return bfd_set_section_contents (output_bfd, stabsec->output_section, |
return bfd_set_section_contents (output_bfd, stabsec->output_section, |
753 |
contents, (file_ptr) stabsec->output_offset, |
contents, (file_ptr) stabsec->output_offset, |
754 |
stabsec->_cooked_size); |
stabsec->size); |
755 |
} |
} |
756 |
|
|
757 |
/* Write out the .stabstr section. */ |
/* Write out the .stabstr section. */ |
758 |
|
|
759 |
boolean |
bfd_boolean |
760 |
_bfd_write_stab_strings (output_bfd, psinfo) |
_bfd_write_stab_strings (output_bfd, sinfo) |
761 |
bfd *output_bfd; |
bfd *output_bfd; |
762 |
PTR *psinfo; |
struct stab_info *sinfo; |
763 |
{ |
{ |
|
struct stab_info *sinfo; |
|
|
|
|
|
sinfo = (struct stab_info *) *psinfo; |
|
|
|
|
|
if (sinfo == NULL) |
|
|
return true; |
|
|
|
|
764 |
if (bfd_is_abs_section (sinfo->stabstr->output_section)) |
if (bfd_is_abs_section (sinfo->stabstr->output_section)) |
765 |
{ |
{ |
766 |
/* The section was discarded from the link. */ |
/* The section was discarded from the link. */ |
767 |
return true; |
return TRUE; |
768 |
} |
} |
769 |
|
|
770 |
BFD_ASSERT ((sinfo->stabstr->output_offset |
BFD_ASSERT ((sinfo->stabstr->output_offset |
771 |
+ _bfd_stringtab_size (sinfo->strings)) |
+ _bfd_stringtab_size (sinfo->strings)) |
772 |
<= sinfo->stabstr->output_section->_raw_size); |
<= sinfo->stabstr->output_section->size); |
773 |
|
|
774 |
if (bfd_seek (output_bfd, |
if (bfd_seek (output_bfd, |
775 |
(file_ptr) (sinfo->stabstr->output_section->filepos |
(file_ptr) (sinfo->stabstr->output_section->filepos |
776 |
+ sinfo->stabstr->output_offset), |
+ sinfo->stabstr->output_offset), |
777 |
SEEK_SET) != 0) |
SEEK_SET) != 0) |
778 |
return false; |
return FALSE; |
779 |
|
|
780 |
if (! _bfd_stringtab_emit (output_bfd, sinfo->strings)) |
if (! _bfd_stringtab_emit (output_bfd, sinfo->strings)) |
781 |
return false; |
return FALSE; |
782 |
|
|
783 |
/* We no longer need the stabs information. */ |
/* We no longer need the stabs information. */ |
784 |
_bfd_stringtab_free (sinfo->strings); |
_bfd_stringtab_free (sinfo->strings); |
785 |
bfd_hash_table_free (&sinfo->includes.root); |
bfd_hash_table_free (&sinfo->includes); |
786 |
|
|
787 |
return true; |
return TRUE; |
788 |
} |
} |
789 |
|
|
790 |
/* Adjust an address in the .stab section. Given OFFSET within |
/* Adjust an address in the .stab section. Given OFFSET within |
792 |
or -1 if the address refers to a stab which has been removed. */ |
or -1 if the address refers to a stab which has been removed. */ |
793 |
|
|
794 |
bfd_vma |
bfd_vma |
795 |
_bfd_stab_section_offset (output_bfd, psinfo, stabsec, psecinfo, offset) |
_bfd_stab_section_offset (stabsec, psecinfo, offset) |
|
bfd *output_bfd ATTRIBUTE_UNUSED; |
|
|
PTR *psinfo ATTRIBUTE_UNUSED; |
|
796 |
asection *stabsec; |
asection *stabsec; |
797 |
PTR *psecinfo; |
PTR psecinfo; |
798 |
bfd_vma offset; |
bfd_vma offset; |
799 |
{ |
{ |
800 |
struct stab_section_info *secinfo; |
struct stab_section_info *secinfo; |
801 |
|
|
802 |
secinfo = (struct stab_section_info *) *psecinfo; |
secinfo = (struct stab_section_info *) psecinfo; |
803 |
|
|
804 |
if (secinfo == NULL) |
if (secinfo == NULL) |
805 |
return offset; |
return offset; |
806 |
|
|
807 |
if (offset >= stabsec->_raw_size) |
if (offset >= stabsec->rawsize) |
808 |
return offset - (stabsec->_cooked_size - stabsec->_raw_size); |
return offset - stabsec->rawsize + stabsec->size; |
809 |
|
|
810 |
if (secinfo->cumulative_skips) |
if (secinfo->cumulative_skips) |
811 |
{ |
{ |