00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "bfd.h"
00030 #include "sysdep.h"
00031 #include "libbfd.h"
00032 #include "aout/stab_gnu.h"
00033 #include "safe-ctype.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define STRDXOFF (0)
00049 #define TYPEOFF (4)
00050 #define OTHEROFF (5)
00051 #define DESCOFF (6)
00052 #define VALOFF (8)
00053 #define STABSIZE (12)
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 struct stab_link_includes_totals
00064 {
00065 struct stab_link_includes_totals *next;
00066 bfd_vma sum_chars;
00067 bfd_vma num_chars;
00068 const char* symb;
00069 };
00070
00071
00072
00073 struct stab_link_includes_entry
00074 {
00075 struct bfd_hash_entry root;
00076
00077 struct stab_link_includes_totals *totals;
00078 };
00079
00080
00081
00082
00083 struct stab_excl_list
00084 {
00085
00086 struct stab_excl_list *next;
00087
00088 bfd_size_type offset;
00089
00090 bfd_vma val;
00091
00092 int type;
00093 };
00094
00095
00096
00097 struct stab_section_info
00098 {
00099
00100
00101 struct stab_excl_list *excls;
00102
00103
00104
00105
00106
00107
00108
00109
00110 bfd_size_type *cumulative_skips;
00111
00112
00113
00114
00115 bfd_size_type stridxs[1];
00116 };
00117
00118 static struct bfd_hash_entry *stab_link_includes_newfunc
00119 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00120
00121
00122
00123 static struct bfd_hash_entry *
00124 stab_link_includes_newfunc (entry, table, string)
00125 struct bfd_hash_entry *entry;
00126 struct bfd_hash_table *table;
00127 const char *string;
00128 {
00129 struct stab_link_includes_entry *ret =
00130 (struct stab_link_includes_entry *) entry;
00131
00132
00133
00134 if (ret == (struct stab_link_includes_entry *) NULL)
00135 ret = ((struct stab_link_includes_entry *)
00136 bfd_hash_allocate (table,
00137 sizeof (struct stab_link_includes_entry)));
00138 if (ret == (struct stab_link_includes_entry *) NULL)
00139 return (struct bfd_hash_entry *) ret;
00140
00141
00142 ret = ((struct stab_link_includes_entry *)
00143 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
00144 if (ret)
00145 {
00146
00147 ret->totals = NULL;
00148 }
00149
00150 return (struct bfd_hash_entry *) ret;
00151 }
00152
00153
00154
00155
00156 bfd_boolean
00157 _bfd_link_section_stabs (abfd, sinfo, stabsec, stabstrsec, psecinfo, pstring_offset)
00158 bfd *abfd;
00159 struct stab_info *sinfo;
00160 asection *stabsec;
00161 asection *stabstrsec;
00162 PTR *psecinfo;
00163 bfd_size_type *pstring_offset;
00164 {
00165 bfd_boolean first;
00166 bfd_size_type count, amt;
00167 struct stab_section_info *secinfo;
00168 bfd_byte *stabbuf = NULL;
00169 bfd_byte *stabstrbuf = NULL;
00170 bfd_byte *sym, *symend;
00171 bfd_size_type stroff, next_stroff, skip;
00172 bfd_size_type *pstridx;
00173
00174 if (stabsec->size == 0
00175 || stabstrsec->size == 0)
00176 {
00177
00178 return TRUE;
00179 }
00180
00181 if (stabsec->size % STABSIZE != 0)
00182 {
00183
00184
00185 return TRUE;
00186 }
00187
00188 if ((stabstrsec->flags & SEC_RELOC) != 0)
00189 {
00190
00191
00192 return TRUE;
00193 }
00194
00195 if ((stabsec->output_section != NULL
00196 && bfd_is_abs_section (stabsec->output_section))
00197 || (stabstrsec->output_section != NULL
00198 && bfd_is_abs_section (stabstrsec->output_section)))
00199 {
00200
00201
00202 return TRUE;
00203 }
00204
00205 first = FALSE;
00206
00207 if (sinfo->stabstr == NULL)
00208 {
00209
00210 first = TRUE;
00211 sinfo->strings = _bfd_stringtab_init ();
00212 if (sinfo->strings == NULL)
00213 goto error_return;
00214
00215 (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
00216 if (! bfd_hash_table_init_n (&sinfo->includes,
00217 stab_link_includes_newfunc,
00218 251))
00219 goto error_return;
00220 sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr");
00221 if (sinfo->stabstr == NULL)
00222 goto error_return;
00223 sinfo->stabstr->flags |= (SEC_HAS_CONTENTS | SEC_READONLY
00224 | SEC_DEBUGGING | SEC_LINKER_CREATED);
00225 }
00226
00227
00228
00229
00230 count = stabsec->size / STABSIZE;
00231
00232 amt = sizeof (struct stab_section_info);
00233 amt += (count - 1) * sizeof (bfd_size_type);
00234 *psecinfo = bfd_alloc (abfd, amt);
00235 if (*psecinfo == NULL)
00236 goto error_return;
00237
00238 secinfo = (struct stab_section_info *) *psecinfo;
00239 secinfo->excls = NULL;
00240 stabsec->rawsize = stabsec->size;
00241 secinfo->cumulative_skips = NULL;
00242 memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
00243
00244
00245
00246 if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
00247 || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
00248 goto error_return;
00249
00250
00251
00252
00253 stroff = 0;
00254
00255
00256
00257
00258 next_stroff = pstring_offset ? *pstring_offset : 0;
00259 skip = 0;
00260
00261 symend = stabbuf + stabsec->size;
00262 for (sym = stabbuf, pstridx = secinfo->stridxs;
00263 sym < symend;
00264 sym += STABSIZE, ++pstridx)
00265 {
00266 bfd_size_type symstroff;
00267 int type;
00268 const char *string;
00269
00270 if (*pstridx != 0)
00271 {
00272
00273 continue;
00274 }
00275
00276 type = sym[TYPEOFF];
00277
00278 if (type == 0)
00279 {
00280
00281
00282 stroff = next_stroff;
00283 next_stroff += bfd_get_32 (abfd, sym + 8);
00284 if (pstring_offset)
00285 *pstring_offset = next_stroff;
00286 if (! first)
00287 {
00288 *pstridx = (bfd_size_type) -1;
00289 ++skip;
00290 continue;
00291 }
00292 first = FALSE;
00293 }
00294
00295
00296 symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
00297 if (symstroff >= stabstrsec->size)
00298 {
00299 (*_bfd_error_handler)
00300 (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
00301 abfd, stabsec, (long) (sym - stabbuf));
00302 bfd_set_error (bfd_error_bad_value);
00303 goto error_return;
00304 }
00305 string = (char *) stabstrbuf + symstroff;
00306 *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
00307
00308
00309
00310
00311
00312
00313 if (type == (int) N_BINCL)
00314 {
00315 bfd_vma sum_chars;
00316 bfd_vma num_chars;
00317 bfd_vma buf_len = 0;
00318 char * symb;
00319 char * symb_rover;
00320 int nest;
00321 bfd_byte * incl_sym;
00322 struct stab_link_includes_entry * incl_entry;
00323 struct stab_link_includes_totals * t;
00324 struct stab_excl_list * ne;
00325
00326 symb = symb_rover = NULL;
00327 sum_chars = num_chars = 0;
00328 nest = 0;
00329
00330 for (incl_sym = sym + STABSIZE;
00331 incl_sym < symend;
00332 incl_sym += STABSIZE)
00333 {
00334 int incl_type;
00335
00336 incl_type = incl_sym[TYPEOFF];
00337 if (incl_type == 0)
00338 break;
00339 else if (incl_type == (int) N_EXCL)
00340 continue;
00341 else if (incl_type == (int) N_EINCL)
00342 {
00343 if (nest == 0)
00344 break;
00345 --nest;
00346 }
00347 else if (incl_type == (int) N_BINCL)
00348 ++nest;
00349 else if (nest == 0)
00350 {
00351 const char *str;
00352
00353 str = ((char *) stabstrbuf
00354 + stroff
00355 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
00356 for (; *str != '\0'; str++)
00357 {
00358 if (num_chars >= buf_len)
00359 {
00360 buf_len += 32 * 1024;
00361 symb = bfd_realloc (symb, buf_len);
00362 if (symb == NULL)
00363 goto error_return;
00364 symb_rover = symb + num_chars;
00365 }
00366 * symb_rover ++ = * str;
00367 sum_chars += *str;
00368 num_chars ++;
00369 if (*str == '(')
00370 {
00371
00372 ++str;
00373 while (ISDIGIT (*str))
00374 ++str;
00375 --str;
00376 }
00377 }
00378 }
00379 }
00380
00381 BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
00382
00383
00384
00385 incl_entry = (struct stab_link_includes_entry * )
00386 bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
00387 if (incl_entry == NULL)
00388 goto error_return;
00389
00390 for (t = incl_entry->totals; t != NULL; t = t->next)
00391 if (t->sum_chars == sum_chars
00392 && t->num_chars == num_chars
00393 && memcmp (t->symb, symb, num_chars) == 0)
00394 break;
00395
00396
00397
00398 amt = sizeof *ne;
00399 ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
00400 if (ne == NULL)
00401 goto error_return;
00402 ne->offset = sym - stabbuf;
00403 ne->val = sum_chars;
00404 ne->type = (int) N_BINCL;
00405 ne->next = secinfo->excls;
00406 secinfo->excls = ne;
00407
00408 if (t == NULL)
00409 {
00410
00411
00412 t = ((struct stab_link_includes_totals *)
00413 bfd_hash_allocate (&sinfo->includes, sizeof *t));
00414 if (t == NULL)
00415 goto error_return;
00416 t->sum_chars = sum_chars;
00417 t->num_chars = num_chars;
00418 t->symb = bfd_realloc (symb, num_chars);
00419 t->next = incl_entry->totals;
00420 incl_entry->totals = t;
00421 }
00422 else
00423 {
00424 bfd_size_type *incl_pstridx;
00425
00426
00427
00428 ne->type = (int) N_EXCL;
00429
00430
00431 free (symb);
00432
00433
00434
00435 nest = 0;
00436 for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
00437 incl_sym < symend;
00438 incl_sym += STABSIZE, ++incl_pstridx)
00439 {
00440 int incl_type;
00441
00442 incl_type = incl_sym[TYPEOFF];
00443
00444 if (incl_type == (int) N_EINCL)
00445 {
00446 if (nest == 0)
00447 {
00448 *incl_pstridx = (bfd_size_type) -1;
00449 ++skip;
00450 break;
00451 }
00452 --nest;
00453 }
00454 else if (incl_type == (int) N_BINCL)
00455 ++nest;
00456 else if (incl_type == (int) N_EXCL)
00457
00458 continue;
00459 else if (nest == 0)
00460 {
00461 *incl_pstridx = (bfd_size_type) -1;
00462 ++skip;
00463 }
00464 }
00465 }
00466 }
00467 }
00468
00469 free (stabbuf);
00470 stabbuf = NULL;
00471 free (stabstrbuf);
00472 stabstrbuf = NULL;
00473
00474
00475
00476
00477
00478
00479
00480
00481 stabsec->size = (count - skip) * STABSIZE;
00482 if (stabsec->size == 0)
00483 stabsec->flags |= SEC_EXCLUDE;
00484 stabstrsec->flags |= SEC_EXCLUDE;
00485 sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
00486
00487
00488
00489
00490 if (skip != 0)
00491 {
00492 bfd_size_type i, offset;
00493 bfd_size_type *pskips;
00494
00495 amt = count * sizeof (bfd_size_type);
00496 secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
00497 if (secinfo->cumulative_skips == NULL)
00498 goto error_return;
00499
00500 pskips = secinfo->cumulative_skips;
00501 pstridx = secinfo->stridxs;
00502 offset = 0;
00503
00504 for (i = 0; i < count; i++, pskips++, pstridx++)
00505 {
00506 *pskips = offset;
00507 if (*pstridx == (bfd_size_type) -1)
00508 offset += STABSIZE;
00509 }
00510
00511 BFD_ASSERT (offset != 0);
00512 }
00513
00514 return TRUE;
00515
00516 error_return:
00517 if (stabbuf != NULL)
00518 free (stabbuf);
00519 if (stabstrbuf != NULL)
00520 free (stabstrbuf);
00521 return FALSE;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530 bfd_boolean
00531 _bfd_discard_section_stabs (abfd, stabsec, psecinfo,
00532 reloc_symbol_deleted_p, cookie)
00533 bfd *abfd;
00534 asection *stabsec;
00535 PTR psecinfo;
00536 bfd_boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR));
00537 PTR cookie;
00538 {
00539 bfd_size_type count, amt;
00540 struct stab_section_info *secinfo;
00541 bfd_byte *stabbuf = NULL;
00542 bfd_byte *sym, *symend;
00543 bfd_size_type skip;
00544 bfd_size_type *pstridx;
00545 int deleting;
00546
00547 if (stabsec->size == 0)
00548 {
00549
00550 return FALSE;
00551 }
00552
00553 if (stabsec->size % STABSIZE != 0)
00554 {
00555
00556
00557 return FALSE;
00558 }
00559
00560 if ((stabsec->output_section != NULL
00561 && bfd_is_abs_section (stabsec->output_section)))
00562 {
00563
00564
00565 return FALSE;
00566 }
00567
00568
00569
00570
00571 if (psecinfo == NULL)
00572 return FALSE;
00573
00574 count = stabsec->rawsize / STABSIZE;
00575 secinfo = (struct stab_section_info *) psecinfo;
00576
00577
00578
00579 if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
00580 goto error_return;
00581
00582
00583
00584
00585 skip = 0;
00586 deleting = -1;
00587
00588 symend = stabbuf + stabsec->rawsize;
00589 for (sym = stabbuf, pstridx = secinfo->stridxs;
00590 sym < symend;
00591 sym += STABSIZE, ++pstridx)
00592 {
00593 int type;
00594
00595 if (*pstridx == (bfd_size_type) -1)
00596 {
00597
00598 continue;
00599 }
00600
00601 type = sym[TYPEOFF];
00602
00603 if (type == (int) N_FUN)
00604 {
00605 int strx = bfd_get_32 (abfd, sym + STRDXOFF);
00606
00607 if (strx == 0)
00608 {
00609 if (deleting)
00610 {
00611 skip++;
00612 *pstridx = -1;
00613 }
00614 deleting = -1;
00615 continue;
00616 }
00617 deleting = 0;
00618 if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
00619 deleting = 1;
00620 }
00621
00622 if (deleting == 1)
00623 {
00624 *pstridx = -1;
00625 skip++;
00626 }
00627 else if (deleting == -1)
00628 {
00629
00630 if (type == (int) N_STSYM || type == (int) N_LCSYM)
00631 if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
00632 {
00633 *pstridx = -1;
00634 skip ++;
00635 }
00636
00637
00638
00639 }
00640 }
00641
00642 free (stabbuf);
00643 stabbuf = NULL;
00644
00645
00646 stabsec->size -= skip * STABSIZE;
00647 if (stabsec->size == 0)
00648 stabsec->flags |= SEC_EXCLUDE;
00649
00650
00651
00652
00653 if (skip != 0)
00654 {
00655 bfd_size_type i, offset;
00656 bfd_size_type *pskips;
00657
00658 if (secinfo->cumulative_skips == NULL)
00659 {
00660 amt = count * sizeof (bfd_size_type);
00661 secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
00662 if (secinfo->cumulative_skips == NULL)
00663 goto error_return;
00664 }
00665
00666 pskips = secinfo->cumulative_skips;
00667 pstridx = secinfo->stridxs;
00668 offset = 0;
00669
00670 for (i = 0; i < count; i++, pskips++, pstridx++)
00671 {
00672 *pskips = offset;
00673 if (*pstridx == (bfd_size_type) -1)
00674 offset += STABSIZE;
00675 }
00676
00677 BFD_ASSERT (offset != 0);
00678 }
00679
00680 return skip > 0;
00681
00682 error_return:
00683 if (stabbuf != NULL)
00684 free (stabbuf);
00685 return FALSE;
00686 }
00687
00688
00689
00690
00691 bfd_boolean
00692 _bfd_write_section_stabs (output_bfd, sinfo, stabsec, psecinfo, contents)
00693 bfd *output_bfd;
00694 struct stab_info *sinfo;
00695 asection *stabsec;
00696 PTR *psecinfo;
00697 bfd_byte *contents;
00698 {
00699 struct stab_section_info *secinfo;
00700 struct stab_excl_list *e;
00701 bfd_byte *sym, *tosym, *symend;
00702 bfd_size_type *pstridx;
00703
00704 secinfo = (struct stab_section_info *) *psecinfo;
00705
00706 if (secinfo == NULL)
00707 return bfd_set_section_contents (output_bfd, stabsec->output_section,
00708 contents, stabsec->output_offset,
00709 stabsec->size);
00710
00711
00712 for (e = secinfo->excls; e != NULL; e = e->next)
00713 {
00714 bfd_byte *excl_sym;
00715
00716 BFD_ASSERT (e->offset < stabsec->rawsize);
00717 excl_sym = contents + e->offset;
00718 bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
00719 excl_sym[TYPEOFF] = e->type;
00720 }
00721
00722
00723
00724 tosym = contents;
00725 symend = contents + stabsec->rawsize;
00726 for (sym = contents, pstridx = secinfo->stridxs;
00727 sym < symend;
00728 sym += STABSIZE, ++pstridx)
00729 {
00730 if (*pstridx != (bfd_size_type) -1)
00731 {
00732 if (tosym != sym)
00733 memcpy (tosym, sym, STABSIZE);
00734 bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
00735
00736 if (sym[TYPEOFF] == 0)
00737 {
00738
00739
00740
00741
00742 BFD_ASSERT (sym == contents);
00743 bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
00744 tosym + VALOFF);
00745 bfd_put_16 (output_bfd,
00746 stabsec->output_section->size / STABSIZE - 1,
00747 tosym + DESCOFF);
00748 }
00749
00750 tosym += STABSIZE;
00751 }
00752 }
00753
00754 BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
00755
00756 return bfd_set_section_contents (output_bfd, stabsec->output_section,
00757 contents, (file_ptr) stabsec->output_offset,
00758 stabsec->size);
00759 }
00760
00761
00762
00763 bfd_boolean
00764 _bfd_write_stab_strings (output_bfd, sinfo)
00765 bfd *output_bfd;
00766 struct stab_info *sinfo;
00767 {
00768 if (bfd_is_abs_section (sinfo->stabstr->output_section))
00769 {
00770
00771 return TRUE;
00772 }
00773
00774 BFD_ASSERT ((sinfo->stabstr->output_offset
00775 + _bfd_stringtab_size (sinfo->strings))
00776 <= sinfo->stabstr->output_section->size);
00777
00778 if (bfd_seek (output_bfd,
00779 (file_ptr) (sinfo->stabstr->output_section->filepos
00780 + sinfo->stabstr->output_offset),
00781 SEEK_SET) != 0)
00782 return FALSE;
00783
00784 if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
00785 return FALSE;
00786
00787
00788 _bfd_stringtab_free (sinfo->strings);
00789 bfd_hash_table_free (&sinfo->includes);
00790
00791 return TRUE;
00792 }
00793
00794
00795
00796
00797
00798 bfd_vma
00799 _bfd_stab_section_offset (stabsec, psecinfo, offset)
00800 asection *stabsec;
00801 PTR psecinfo;
00802 bfd_vma offset;
00803 {
00804 struct stab_section_info *secinfo;
00805
00806 secinfo = (struct stab_section_info *) psecinfo;
00807
00808 if (secinfo == NULL)
00809 return offset;
00810
00811 if (offset >= stabsec->rawsize)
00812 return offset - stabsec->rawsize + stabsec->size;
00813
00814 if (secinfo->cumulative_skips)
00815 {
00816 bfd_vma i;
00817
00818 i = offset / STABSIZE;
00819
00820 if (secinfo->stridxs [i] == (bfd_size_type) -1)
00821 return (bfd_vma) -1;
00822
00823 return offset - secinfo->cumulative_skips [i];
00824 }
00825
00826 return offset;
00827 }