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