133965Sjdp/* Stabs in sections linking support. 2218822Sdim Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 3218822Sdim 2006, 2007 Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor, Cygnus Support. 533965Sjdp 6130561Sobrien This file is part of BFD, the Binary File Descriptor library. 733965Sjdp 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2 of the License, or 11130561Sobrien (at your option) any later version. 1233965Sjdp 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 1733965Sjdp 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp/* This file contains support for linking stabs in sections, as used 2333965Sjdp on COFF and ELF. */ 2433965Sjdp 25218822Sdim#include "sysdep.h" 2633965Sjdp#include "bfd.h" 2733965Sjdp#include "libbfd.h" 2833965Sjdp#include "aout/stab_gnu.h" 2989857Sobrien#include "safe-ctype.h" 3033965Sjdp 3133965Sjdp/* Stabs entries use a 12 byte format: 3233965Sjdp 4 byte string table index 3333965Sjdp 1 byte stab type 3433965Sjdp 1 byte stab other field 3533965Sjdp 2 byte stab desc field 3633965Sjdp 4 byte stab value 3733965Sjdp FIXME: This will have to change for a 64 bit object format. 3833965Sjdp 3933965Sjdp The stabs symbols are divided into compilation units. For the 4033965Sjdp first entry in each unit, the type of 0, the value is the length of 4133965Sjdp the string table for this unit, and the desc field is the number of 4233965Sjdp stabs symbols for this unit. */ 4333965Sjdp 44218822Sdim#define STRDXOFF 0 45218822Sdim#define TYPEOFF 4 46218822Sdim#define OTHEROFF 5 47218822Sdim#define DESCOFF 6 48218822Sdim#define VALOFF 8 49218822Sdim#define STABSIZE 12 5033965Sjdp 5133965Sjdp/* A linked list of totals that we have found for a particular header 52130561Sobrien file. A total is a unique identifier for a particular BINCL...EINCL 53130561Sobrien sequence of STABs that can be used to identify duplicate sequences. 54130561Sobrien It consists of three fields, 'sum_chars' which is the sum of all the 55130561Sobrien STABS characters; 'num_chars' which is the number of these charactes 56130561Sobrien and 'symb' which is a buffer of all the symbols in the sequence. This 57130561Sobrien buffer is only checked as a last resort. */ 5833965Sjdp 5933965Sjdpstruct stab_link_includes_totals 6033965Sjdp{ 6133965Sjdp struct stab_link_includes_totals *next; 62130561Sobrien bfd_vma sum_chars; /* Accumulated sum of STABS characters. */ 63130561Sobrien bfd_vma num_chars; /* Number of STABS characters. */ 64130561Sobrien const char* symb; /* The STABS characters themselves. */ 6533965Sjdp}; 6633965Sjdp 6733965Sjdp/* An entry in the header file hash table. */ 6833965Sjdp 6933965Sjdpstruct stab_link_includes_entry 7033965Sjdp{ 7133965Sjdp struct bfd_hash_entry root; 7233965Sjdp /* List of totals we have found for this file. */ 7333965Sjdp struct stab_link_includes_totals *totals; 7433965Sjdp}; 7533965Sjdp 7633965Sjdp/* This structure is used to hold a list of N_BINCL symbols, some of 7733965Sjdp which might be converted into N_EXCL symbols. */ 7833965Sjdp 7933965Sjdpstruct stab_excl_list 8033965Sjdp{ 8133965Sjdp /* The next symbol to convert. */ 8233965Sjdp struct stab_excl_list *next; 8333965Sjdp /* The offset to this symbol in the section contents. */ 8433965Sjdp bfd_size_type offset; 8533965Sjdp /* The value to use for the symbol. */ 8633965Sjdp bfd_vma val; 8733965Sjdp /* The type of this symbol (N_BINCL or N_EXCL). */ 8833965Sjdp int type; 8933965Sjdp}; 9033965Sjdp 9133965Sjdp/* This structure is stored with each .stab section. */ 9233965Sjdp 9333965Sjdpstruct stab_section_info 9433965Sjdp{ 9533965Sjdp /* This is a linked list of N_BINCL symbols which should be 9633965Sjdp converted into N_EXCL symbols. */ 9733965Sjdp struct stab_excl_list *excls; 9833965Sjdp 9933965Sjdp /* This is used to map input stab offsets within their sections 10033965Sjdp to output stab offsets, to take into account stabs that have 10133965Sjdp been deleted. If it is NULL, the output offsets are the same 10233965Sjdp as the input offsets, because no stabs have been deleted from 10333965Sjdp this section. Otherwise the i'th entry is the number of 10433965Sjdp bytes of stabs that have been deleted prior to the i'th 10577298Sobrien stab. */ 10633965Sjdp bfd_size_type *cumulative_skips; 10733965Sjdp 10833965Sjdp /* This is an array of string indices. For each stab symbol, we 10933965Sjdp store the string index here. If a stab symbol should not be 11033965Sjdp included in the final output, the string index is -1. */ 11133965Sjdp bfd_size_type stridxs[1]; 11233965Sjdp}; 11333965Sjdp 11433965Sjdp 11533965Sjdp/* The function to create a new entry in the header file hash table. */ 11633965Sjdp 11733965Sjdpstatic struct bfd_hash_entry * 118218822Sdimstab_link_includes_newfunc (struct bfd_hash_entry *entry, 119218822Sdim struct bfd_hash_table *table, 120218822Sdim const char *string) 12133965Sjdp{ 12233965Sjdp struct stab_link_includes_entry *ret = 12333965Sjdp (struct stab_link_includes_entry *) entry; 12433965Sjdp 12533965Sjdp /* Allocate the structure if it has not already been allocated by a 12633965Sjdp subclass. */ 127218822Sdim if (ret == NULL) 128218822Sdim ret = bfd_hash_allocate (table, 129218822Sdim sizeof (struct stab_link_includes_entry)); 130218822Sdim if (ret == NULL) 131218822Sdim return NULL; 13233965Sjdp 13333965Sjdp /* Call the allocation method of the superclass. */ 13433965Sjdp ret = ((struct stab_link_includes_entry *) 13533965Sjdp bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 13633965Sjdp if (ret) 137218822Sdim /* Set local fields. */ 138218822Sdim ret->totals = NULL; 13933965Sjdp 14033965Sjdp return (struct bfd_hash_entry *) ret; 14133965Sjdp} 14233965Sjdp 14333965Sjdp/* This function is called for each input file from the add_symbols 14433965Sjdp pass of the linker. */ 14533965Sjdp 146130561Sobrienbfd_boolean 147218822Sdim_bfd_link_section_stabs (bfd *abfd, 148218822Sdim struct stab_info *sinfo, 149218822Sdim asection *stabsec, 150218822Sdim asection *stabstrsec, 151218822Sdim void * *psecinfo, 152218822Sdim bfd_size_type *pstring_offset) 15333965Sjdp{ 154130561Sobrien bfd_boolean first; 15589857Sobrien bfd_size_type count, amt; 15633965Sjdp struct stab_section_info *secinfo; 15733965Sjdp bfd_byte *stabbuf = NULL; 15833965Sjdp bfd_byte *stabstrbuf = NULL; 15933965Sjdp bfd_byte *sym, *symend; 16033965Sjdp bfd_size_type stroff, next_stroff, skip; 16133965Sjdp bfd_size_type *pstridx; 16233965Sjdp 163218822Sdim if (stabsec->size == 0 164218822Sdim || stabstrsec->size == 0) 165218822Sdim /* This file does not contain stabs debugging information. */ 166218822Sdim return TRUE; 16733965Sjdp 168218822Sdim if (stabsec->size % STABSIZE != 0) 169218822Sdim /* Something is wrong with the format of these stab symbols. 170218822Sdim Don't try to optimize them. */ 171218822Sdim return TRUE; 17233965Sjdp 17333965Sjdp if ((stabstrsec->flags & SEC_RELOC) != 0) 174218822Sdim /* We shouldn't see relocations in the strings, and we aren't 175218822Sdim prepared to handle them. */ 176218822Sdim return TRUE; 17733965Sjdp 178218822Sdim if (bfd_is_abs_section (stabsec->output_section) 179218822Sdim || bfd_is_abs_section (stabstrsec->output_section)) 180218822Sdim /* At least one of the sections is being discarded from the 181218822Sdim link, so we should just ignore them. */ 182218822Sdim return TRUE; 18333965Sjdp 184130561Sobrien first = FALSE; 18533965Sjdp 186218822Sdim if (sinfo->stabstr == NULL) 18733965Sjdp { 188218822Sdim flagword flags; 189218822Sdim 19033965Sjdp /* Initialize the stabs information we need to keep track of. */ 191130561Sobrien first = TRUE; 19233965Sjdp sinfo->strings = _bfd_stringtab_init (); 19333965Sjdp if (sinfo->strings == NULL) 19433965Sjdp goto error_return; 19560484Sobrien /* Make sure the first byte is zero. */ 196130561Sobrien (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE); 197218822Sdim if (! bfd_hash_table_init (&sinfo->includes, 198218822Sdim stab_link_includes_newfunc, 199218822Sdim sizeof (struct stab_link_includes_entry))) 20033965Sjdp goto error_return; 201218822Sdim flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING 202218822Sdim | SEC_LINKER_CREATED); 203218822Sdim sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr", 204218822Sdim flags); 205218822Sdim if (sinfo->stabstr == NULL) 206218822Sdim goto error_return; 20733965Sjdp } 20833965Sjdp 20933965Sjdp /* Initialize the information we are going to store for this .stab 21033965Sjdp section. */ 211218822Sdim count = stabsec->size / STABSIZE; 21233965Sjdp 21389857Sobrien amt = sizeof (struct stab_section_info); 21489857Sobrien amt += (count - 1) * sizeof (bfd_size_type); 21589857Sobrien *psecinfo = bfd_alloc (abfd, amt); 21633965Sjdp if (*psecinfo == NULL) 21733965Sjdp goto error_return; 21833965Sjdp 21933965Sjdp secinfo = (struct stab_section_info *) *psecinfo; 22033965Sjdp secinfo->excls = NULL; 221218822Sdim stabsec->rawsize = stabsec->size; 22233965Sjdp secinfo->cumulative_skips = NULL; 22389857Sobrien memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type)); 22433965Sjdp 22533965Sjdp /* Read the stabs information from abfd. */ 226218822Sdim if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf) 227218822Sdim || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf)) 22833965Sjdp goto error_return; 22933965Sjdp 23033965Sjdp /* Look through the stabs symbols, work out the new string indices, 23133965Sjdp and identify N_BINCL symbols which can be eliminated. */ 23233965Sjdp stroff = 0; 233130561Sobrien /* The stabs sections can be split when 234130561Sobrien -split-by-reloc/-split-by-file is used. We must keep track of 235130561Sobrien each stab section's place in the single concatenated string 236130561Sobrien table. */ 237130561Sobrien next_stroff = pstring_offset ? *pstring_offset : 0; 23833965Sjdp skip = 0; 23933965Sjdp 240218822Sdim symend = stabbuf + stabsec->size; 24133965Sjdp for (sym = stabbuf, pstridx = secinfo->stridxs; 24233965Sjdp sym < symend; 24333965Sjdp sym += STABSIZE, ++pstridx) 24433965Sjdp { 245104834Sobrien bfd_size_type symstroff; 24633965Sjdp int type; 24733965Sjdp const char *string; 24833965Sjdp 24933965Sjdp if (*pstridx != 0) 250218822Sdim /* This symbol has already been handled by an N_BINCL pass. */ 251218822Sdim continue; 25233965Sjdp 25333965Sjdp type = sym[TYPEOFF]; 25433965Sjdp 25533965Sjdp if (type == 0) 25633965Sjdp { 25733965Sjdp /* Special type 0 stabs indicate the offset to the next 258130561Sobrien string table. We only copy the very first one. */ 25933965Sjdp stroff = next_stroff; 26033965Sjdp next_stroff += bfd_get_32 (abfd, sym + 8); 261130561Sobrien if (pstring_offset) 262130561Sobrien *pstring_offset = next_stroff; 26333965Sjdp if (! first) 26433965Sjdp { 26533965Sjdp *pstridx = (bfd_size_type) -1; 26633965Sjdp ++skip; 26733965Sjdp continue; 26833965Sjdp } 269130561Sobrien first = FALSE; 27033965Sjdp } 27133965Sjdp 27233965Sjdp /* Store the string in the hash table, and record the index. */ 273104834Sobrien symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF); 274218822Sdim if (symstroff >= stabstrsec->size) 275104834Sobrien { 276104834Sobrien (*_bfd_error_handler) 277218822Sdim (_("%B(%A+0x%lx): Stabs entry has invalid string index."), 278218822Sdim abfd, stabsec, (long) (sym - stabbuf)); 279104834Sobrien bfd_set_error (bfd_error_bad_value); 280104834Sobrien goto error_return; 281104834Sobrien } 282104834Sobrien string = (char *) stabstrbuf + symstroff; 283130561Sobrien *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE); 28433965Sjdp 28533965Sjdp /* An N_BINCL symbol indicates the start of the stabs entries 28633965Sjdp for a header file. We need to scan ahead to the next N_EINCL 28733965Sjdp symbol, ignoring nesting, adding up all the characters in the 28833965Sjdp symbol names, not including the file numbers in types (the 28933965Sjdp first number after an open parenthesis). */ 290107492Sobrien if (type == (int) N_BINCL) 29133965Sjdp { 292130561Sobrien bfd_vma sum_chars; 293130561Sobrien bfd_vma num_chars; 294130561Sobrien bfd_vma buf_len = 0; 295130561Sobrien char * symb; 296130561Sobrien char * symb_rover; 29733965Sjdp int nest; 298130561Sobrien bfd_byte * incl_sym; 299130561Sobrien struct stab_link_includes_entry * incl_entry; 300130561Sobrien struct stab_link_includes_totals * t; 301130561Sobrien struct stab_excl_list * ne; 30233965Sjdp 303130561Sobrien symb = symb_rover = NULL; 304130561Sobrien sum_chars = num_chars = 0; 30533965Sjdp nest = 0; 306130561Sobrien 30733965Sjdp for (incl_sym = sym + STABSIZE; 30833965Sjdp incl_sym < symend; 30933965Sjdp incl_sym += STABSIZE) 31033965Sjdp { 31133965Sjdp int incl_type; 31233965Sjdp 31333965Sjdp incl_type = incl_sym[TYPEOFF]; 31433965Sjdp if (incl_type == 0) 31533965Sjdp break; 316130561Sobrien else if (incl_type == (int) N_EXCL) 317130561Sobrien continue; 318107492Sobrien else if (incl_type == (int) N_EINCL) 31933965Sjdp { 32033965Sjdp if (nest == 0) 32133965Sjdp break; 32233965Sjdp --nest; 32333965Sjdp } 324107492Sobrien else if (incl_type == (int) N_BINCL) 32533965Sjdp ++nest; 32633965Sjdp else if (nest == 0) 32733965Sjdp { 32833965Sjdp const char *str; 32933965Sjdp 33033965Sjdp str = ((char *) stabstrbuf 33133965Sjdp + stroff 33233965Sjdp + bfd_get_32 (abfd, incl_sym + STRDXOFF)); 33333965Sjdp for (; *str != '\0'; str++) 33433965Sjdp { 335130561Sobrien if (num_chars >= buf_len) 336130561Sobrien { 337130561Sobrien buf_len += 32 * 1024; 338130561Sobrien symb = bfd_realloc (symb, buf_len); 339130561Sobrien if (symb == NULL) 340130561Sobrien goto error_return; 341130561Sobrien symb_rover = symb + num_chars; 342130561Sobrien } 343130561Sobrien * symb_rover ++ = * str; 344130561Sobrien sum_chars += *str; 345130561Sobrien num_chars ++; 34633965Sjdp if (*str == '(') 34733965Sjdp { 34833965Sjdp /* Skip the file number. */ 34933965Sjdp ++str; 35089857Sobrien while (ISDIGIT (*str)) 35133965Sjdp ++str; 35233965Sjdp --str; 35333965Sjdp } 35433965Sjdp } 35533965Sjdp } 35633965Sjdp } 35733965Sjdp 358130561Sobrien BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb)); 359130561Sobrien 36033965Sjdp /* If we have already included a header file with the same 36133965Sjdp value, then replaced this one with an N_EXCL symbol. */ 362218822Sdim incl_entry = (struct stab_link_includes_entry * ) 363218822Sdim bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE); 36433965Sjdp if (incl_entry == NULL) 36533965Sjdp goto error_return; 36633965Sjdp 36733965Sjdp for (t = incl_entry->totals; t != NULL; t = t->next) 368130561Sobrien if (t->sum_chars == sum_chars 369130561Sobrien && t->num_chars == num_chars 370130561Sobrien && memcmp (t->symb, symb, num_chars) == 0) 37133965Sjdp break; 37233965Sjdp 37333965Sjdp /* Record this symbol, so that we can set the value 374130561Sobrien correctly. */ 37589857Sobrien amt = sizeof *ne; 376218822Sdim ne = bfd_alloc (abfd, amt); 37733965Sjdp if (ne == NULL) 37833965Sjdp goto error_return; 37933965Sjdp ne->offset = sym - stabbuf; 380130561Sobrien ne->val = sum_chars; 381107492Sobrien ne->type = (int) N_BINCL; 38233965Sjdp ne->next = secinfo->excls; 38333965Sjdp secinfo->excls = ne; 38433965Sjdp 38533965Sjdp if (t == NULL) 38633965Sjdp { 38733965Sjdp /* This is the first time we have seen this header file 38833965Sjdp with this set of stabs strings. */ 389218822Sdim t = bfd_hash_allocate (&sinfo->includes, sizeof *t); 39033965Sjdp if (t == NULL) 39133965Sjdp goto error_return; 392130561Sobrien t->sum_chars = sum_chars; 393130561Sobrien t->num_chars = num_chars; 394130561Sobrien t->symb = bfd_realloc (symb, num_chars); /* Trim data down. */ 39533965Sjdp t->next = incl_entry->totals; 39633965Sjdp incl_entry->totals = t; 39733965Sjdp } 39833965Sjdp else 39933965Sjdp { 40033965Sjdp bfd_size_type *incl_pstridx; 40133965Sjdp 40233965Sjdp /* We have seen this header file before. Tell the final 40333965Sjdp pass to change the type to N_EXCL. */ 404107492Sobrien ne->type = (int) N_EXCL; 40533965Sjdp 406130561Sobrien /* Free off superfluous symbols. */ 407130561Sobrien free (symb); 408130561Sobrien 40933965Sjdp /* Mark the skipped symbols. */ 41033965Sjdp 41133965Sjdp nest = 0; 41233965Sjdp for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1; 41333965Sjdp incl_sym < symend; 41433965Sjdp incl_sym += STABSIZE, ++incl_pstridx) 41533965Sjdp { 41633965Sjdp int incl_type; 41733965Sjdp 41833965Sjdp incl_type = incl_sym[TYPEOFF]; 41933965Sjdp 420107492Sobrien if (incl_type == (int) N_EINCL) 42133965Sjdp { 42233965Sjdp if (nest == 0) 42333965Sjdp { 42433965Sjdp *incl_pstridx = (bfd_size_type) -1; 42533965Sjdp ++skip; 42633965Sjdp break; 42733965Sjdp } 42833965Sjdp --nest; 42933965Sjdp } 430107492Sobrien else if (incl_type == (int) N_BINCL) 43133965Sjdp ++nest; 432130561Sobrien else if (incl_type == (int) N_EXCL) 433130561Sobrien /* Keep existing exclusion marks. */ 434218822Sdim continue; 43533965Sjdp else if (nest == 0) 43633965Sjdp { 43733965Sjdp *incl_pstridx = (bfd_size_type) -1; 43833965Sjdp ++skip; 43933965Sjdp } 44033965Sjdp } 44133965Sjdp } 44233965Sjdp } 44333965Sjdp } 44433965Sjdp 44533965Sjdp free (stabbuf); 44633965Sjdp stabbuf = NULL; 44733965Sjdp free (stabstrbuf); 44833965Sjdp stabstrbuf = NULL; 44933965Sjdp 45033965Sjdp /* We need to set the section sizes such that the linker will 45133965Sjdp compute the output section sizes correctly. We set the .stab 45233965Sjdp size to not include the entries we don't want. We set 45333965Sjdp SEC_EXCLUDE for the .stabstr section, so that it will be dropped 45433965Sjdp from the link. We record the size of the strtab in the first 45533965Sjdp .stabstr section we saw, and make sure we don't set SEC_EXCLUDE 45633965Sjdp for that section. */ 457218822Sdim stabsec->size = (count - skip) * STABSIZE; 458218822Sdim if (stabsec->size == 0) 459218822Sdim stabsec->flags |= SEC_EXCLUDE | SEC_KEEP; 460218822Sdim stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP; 461218822Sdim sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings); 46233965Sjdp 46333965Sjdp /* Calculate the `cumulative_skips' array now that stabs have been 46477298Sobrien deleted for this section. */ 46533965Sjdp 46633965Sjdp if (skip != 0) 46733965Sjdp { 46833965Sjdp bfd_size_type i, offset; 46933965Sjdp bfd_size_type *pskips; 47033965Sjdp 47189857Sobrien amt = count * sizeof (bfd_size_type); 472218822Sdim secinfo->cumulative_skips = bfd_alloc (abfd, amt); 47333965Sjdp if (secinfo->cumulative_skips == NULL) 47433965Sjdp goto error_return; 47533965Sjdp 47633965Sjdp pskips = secinfo->cumulative_skips; 47733965Sjdp pstridx = secinfo->stridxs; 47833965Sjdp offset = 0; 47933965Sjdp 48033965Sjdp for (i = 0; i < count; i++, pskips++, pstridx++) 48133965Sjdp { 48233965Sjdp *pskips = offset; 48333965Sjdp if (*pstridx == (bfd_size_type) -1) 48433965Sjdp offset += STABSIZE; 48533965Sjdp } 48633965Sjdp 48733965Sjdp BFD_ASSERT (offset != 0); 48833965Sjdp } 48933965Sjdp 490130561Sobrien return TRUE; 49133965Sjdp 49233965Sjdp error_return: 49333965Sjdp if (stabbuf != NULL) 49433965Sjdp free (stabbuf); 49533965Sjdp if (stabstrbuf != NULL) 49633965Sjdp free (stabstrbuf); 497130561Sobrien return FALSE; 49833965Sjdp} 49989857Sobrien 50089857Sobrien/* This function is called for each input file before the stab 50189857Sobrien section is relocated. It discards stab entries for discarded 502130561Sobrien functions and variables. The function returns TRUE iff 50389857Sobrien any entries have been deleted. 50489857Sobrien*/ 50589857Sobrien 506130561Sobrienbfd_boolean 507218822Sdim_bfd_discard_section_stabs (bfd *abfd, 508218822Sdim asection *stabsec, 509218822Sdim void * psecinfo, 510218822Sdim bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *), 511218822Sdim void * cookie) 51289857Sobrien{ 51389857Sobrien bfd_size_type count, amt; 51489857Sobrien struct stab_section_info *secinfo; 51589857Sobrien bfd_byte *stabbuf = NULL; 51689857Sobrien bfd_byte *sym, *symend; 51789857Sobrien bfd_size_type skip; 51889857Sobrien bfd_size_type *pstridx; 51989857Sobrien int deleting; 52089857Sobrien 521218822Sdim if (stabsec->size == 0) 522218822Sdim /* This file does not contain stabs debugging information. */ 523218822Sdim return FALSE; 52489857Sobrien 525218822Sdim if (stabsec->size % STABSIZE != 0) 526218822Sdim /* Something is wrong with the format of these stab symbols. 527218822Sdim Don't try to optimize them. */ 528218822Sdim return FALSE; 52989857Sobrien 53089857Sobrien if ((stabsec->output_section != NULL 53189857Sobrien && bfd_is_abs_section (stabsec->output_section))) 532218822Sdim /* At least one of the sections is being discarded from the 533218822Sdim link, so we should just ignore them. */ 534218822Sdim return FALSE; 53589857Sobrien 53689857Sobrien /* We should have initialized our data in _bfd_link_stab_sections. 53789857Sobrien If there was some bizarre error reading the string sections, though, 53889857Sobrien we might not have. Bail rather than asserting. */ 53989857Sobrien if (psecinfo == NULL) 540130561Sobrien return FALSE; 54189857Sobrien 542218822Sdim count = stabsec->rawsize / STABSIZE; 54389857Sobrien secinfo = (struct stab_section_info *) psecinfo; 54489857Sobrien 54589857Sobrien /* Read the stabs information from abfd. */ 546218822Sdim if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)) 54789857Sobrien goto error_return; 54889857Sobrien 54989857Sobrien /* Look through the stabs symbols and discard any information for 55089857Sobrien discarded functions. */ 55189857Sobrien skip = 0; 55289857Sobrien deleting = -1; 55389857Sobrien 554218822Sdim symend = stabbuf + stabsec->rawsize; 55589857Sobrien for (sym = stabbuf, pstridx = secinfo->stridxs; 55689857Sobrien sym < symend; 55789857Sobrien sym += STABSIZE, ++pstridx) 55889857Sobrien { 55989857Sobrien int type; 56089857Sobrien 56189857Sobrien if (*pstridx == (bfd_size_type) -1) 562218822Sdim /* This stab was deleted in a previous pass. */ 563218822Sdim continue; 56489857Sobrien 56589857Sobrien type = sym[TYPEOFF]; 56689857Sobrien 567107492Sobrien if (type == (int) N_FUN) 56889857Sobrien { 56989857Sobrien int strx = bfd_get_32 (abfd, sym + STRDXOFF); 57089857Sobrien 57189857Sobrien if (strx == 0) 57289857Sobrien { 57389857Sobrien if (deleting) 57489857Sobrien { 57589857Sobrien skip++; 57689857Sobrien *pstridx = -1; 57789857Sobrien } 57889857Sobrien deleting = -1; 57989857Sobrien continue; 58089857Sobrien } 58189857Sobrien deleting = 0; 58289857Sobrien if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) 58389857Sobrien deleting = 1; 58489857Sobrien } 58589857Sobrien 58689857Sobrien if (deleting == 1) 58789857Sobrien { 58889857Sobrien *pstridx = -1; 58989857Sobrien skip++; 59089857Sobrien } 59189857Sobrien else if (deleting == -1) 59289857Sobrien { 59389857Sobrien /* Outside of a function. Check for deleted variables. */ 594107492Sobrien if (type == (int) N_STSYM || type == (int) N_LCSYM) 59589857Sobrien if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) 59689857Sobrien { 59789857Sobrien *pstridx = -1; 59889857Sobrien skip ++; 59989857Sobrien } 60089857Sobrien /* We should also check for N_GSYM entries which reference a 60189857Sobrien deleted global, but those are less harmful to debuggers 60289857Sobrien and would require parsing the stab strings. */ 60389857Sobrien } 60489857Sobrien } 60589857Sobrien 60689857Sobrien free (stabbuf); 60789857Sobrien stabbuf = NULL; 60889857Sobrien 60989857Sobrien /* Shrink the stabsec as needed. */ 610218822Sdim stabsec->size -= skip * STABSIZE; 611218822Sdim if (stabsec->size == 0) 612218822Sdim stabsec->flags |= SEC_EXCLUDE | SEC_KEEP; 61389857Sobrien 61489857Sobrien /* Recalculate the `cumulative_skips' array now that stabs have been 61589857Sobrien deleted for this section. */ 61689857Sobrien 61789857Sobrien if (skip != 0) 61889857Sobrien { 61989857Sobrien bfd_size_type i, offset; 62089857Sobrien bfd_size_type *pskips; 62189857Sobrien 62289857Sobrien if (secinfo->cumulative_skips == NULL) 62389857Sobrien { 62489857Sobrien amt = count * sizeof (bfd_size_type); 625218822Sdim secinfo->cumulative_skips = bfd_alloc (abfd, amt); 62689857Sobrien if (secinfo->cumulative_skips == NULL) 62789857Sobrien goto error_return; 62889857Sobrien } 62989857Sobrien 63089857Sobrien pskips = secinfo->cumulative_skips; 63189857Sobrien pstridx = secinfo->stridxs; 63289857Sobrien offset = 0; 63389857Sobrien 63489857Sobrien for (i = 0; i < count; i++, pskips++, pstridx++) 63589857Sobrien { 63689857Sobrien *pskips = offset; 63789857Sobrien if (*pstridx == (bfd_size_type) -1) 63889857Sobrien offset += STABSIZE; 63989857Sobrien } 64089857Sobrien 64189857Sobrien BFD_ASSERT (offset != 0); 64289857Sobrien } 64389857Sobrien 644130561Sobrien return skip > 0; 64589857Sobrien 64689857Sobrien error_return: 64789857Sobrien if (stabbuf != NULL) 64889857Sobrien free (stabbuf); 649130561Sobrien return FALSE; 65089857Sobrien} 65189857Sobrien 65233965Sjdp/* Write out the stab section. This is called with the relocated 65333965Sjdp contents. */ 65433965Sjdp 655130561Sobrienbfd_boolean 656218822Sdim_bfd_write_section_stabs (bfd *output_bfd, 657218822Sdim struct stab_info *sinfo, 658218822Sdim asection *stabsec, 659218822Sdim void * *psecinfo, 660218822Sdim bfd_byte *contents) 66133965Sjdp{ 66233965Sjdp struct stab_section_info *secinfo; 66333965Sjdp struct stab_excl_list *e; 66433965Sjdp bfd_byte *sym, *tosym, *symend; 66533965Sjdp bfd_size_type *pstridx; 66633965Sjdp 66733965Sjdp secinfo = (struct stab_section_info *) *psecinfo; 66833965Sjdp 66933965Sjdp if (secinfo == NULL) 67033965Sjdp return bfd_set_section_contents (output_bfd, stabsec->output_section, 671218822Sdim contents, stabsec->output_offset, 672218822Sdim stabsec->size); 67333965Sjdp 67433965Sjdp /* Handle each N_BINCL entry. */ 67533965Sjdp for (e = secinfo->excls; e != NULL; e = e->next) 67633965Sjdp { 67733965Sjdp bfd_byte *excl_sym; 67833965Sjdp 679218822Sdim BFD_ASSERT (e->offset < stabsec->rawsize); 68033965Sjdp excl_sym = contents + e->offset; 68133965Sjdp bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF); 68233965Sjdp excl_sym[TYPEOFF] = e->type; 68333965Sjdp } 68433965Sjdp 68533965Sjdp /* Copy over all the stabs symbols, omitting the ones we don't want, 68633965Sjdp and correcting the string indices for those we do want. */ 68733965Sjdp tosym = contents; 688218822Sdim symend = contents + stabsec->rawsize; 68933965Sjdp for (sym = contents, pstridx = secinfo->stridxs; 69033965Sjdp sym < symend; 69133965Sjdp sym += STABSIZE, ++pstridx) 69233965Sjdp { 69333965Sjdp if (*pstridx != (bfd_size_type) -1) 69433965Sjdp { 69533965Sjdp if (tosym != sym) 69633965Sjdp memcpy (tosym, sym, STABSIZE); 69733965Sjdp bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF); 69833965Sjdp 69933965Sjdp if (sym[TYPEOFF] == 0) 70033965Sjdp { 70133965Sjdp /* This is the header symbol for the stabs section. We 702130561Sobrien don't really need one, since we have merged all the 703130561Sobrien input stabs sections into one, but we generate one 704130561Sobrien for the benefit of readers which expect to see one. */ 70533965Sjdp BFD_ASSERT (sym == contents); 70633965Sjdp bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings), 70733965Sjdp tosym + VALOFF); 70833965Sjdp bfd_put_16 (output_bfd, 709218822Sdim stabsec->output_section->size / STABSIZE - 1, 71033965Sjdp tosym + DESCOFF); 71133965Sjdp } 71233965Sjdp 71333965Sjdp tosym += STABSIZE; 71433965Sjdp } 71533965Sjdp } 71633965Sjdp 717218822Sdim BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size); 71833965Sjdp 71933965Sjdp return bfd_set_section_contents (output_bfd, stabsec->output_section, 72089857Sobrien contents, (file_ptr) stabsec->output_offset, 721218822Sdim stabsec->size); 72233965Sjdp} 72333965Sjdp 72433965Sjdp/* Write out the .stabstr section. */ 72533965Sjdp 726130561Sobrienbfd_boolean 727218822Sdim_bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo) 72833965Sjdp{ 729218822Sdim if (bfd_is_abs_section (sinfo->stabstr->output_section)) 730218822Sdim /* The section was discarded from the link. */ 731130561Sobrien return TRUE; 73233965Sjdp 73333965Sjdp BFD_ASSERT ((sinfo->stabstr->output_offset 73433965Sjdp + _bfd_stringtab_size (sinfo->strings)) 735218822Sdim <= sinfo->stabstr->output_section->size); 73633965Sjdp 73733965Sjdp if (bfd_seek (output_bfd, 73889857Sobrien (file_ptr) (sinfo->stabstr->output_section->filepos 73989857Sobrien + sinfo->stabstr->output_offset), 74033965Sjdp SEEK_SET) != 0) 741130561Sobrien return FALSE; 74233965Sjdp 74333965Sjdp if (! _bfd_stringtab_emit (output_bfd, sinfo->strings)) 744130561Sobrien return FALSE; 74533965Sjdp 74633965Sjdp /* We no longer need the stabs information. */ 74733965Sjdp _bfd_stringtab_free (sinfo->strings); 748218822Sdim bfd_hash_table_free (&sinfo->includes); 74933965Sjdp 750130561Sobrien return TRUE; 75133965Sjdp} 75233965Sjdp 75333965Sjdp/* Adjust an address in the .stab section. Given OFFSET within 75433965Sjdp STABSEC, this returns the new offset in the adjusted stab section, 75533965Sjdp or -1 if the address refers to a stab which has been removed. */ 75633965Sjdp 75733965Sjdpbfd_vma 758218822Sdim_bfd_stab_section_offset (asection *stabsec, 759218822Sdim void * psecinfo, 760218822Sdim bfd_vma offset) 76133965Sjdp{ 76233965Sjdp struct stab_section_info *secinfo; 76333965Sjdp 764218822Sdim secinfo = (struct stab_section_info *) psecinfo; 76533965Sjdp 76633965Sjdp if (secinfo == NULL) 76733965Sjdp return offset; 76833965Sjdp 769218822Sdim if (offset >= stabsec->rawsize) 770218822Sdim return offset - stabsec->rawsize + stabsec->size; 77133965Sjdp 77233965Sjdp if (secinfo->cumulative_skips) 77333965Sjdp { 77433965Sjdp bfd_vma i; 77533965Sjdp 77633965Sjdp i = offset / STABSIZE; 77733965Sjdp 77833965Sjdp if (secinfo->stridxs [i] == (bfd_size_type) -1) 77933965Sjdp return (bfd_vma) -1; 78033965Sjdp 78133965Sjdp return offset - secinfo->cumulative_skips [i]; 78233965Sjdp } 78333965Sjdp 78433965Sjdp return offset; 78533965Sjdp} 786