1 /* SEC_MERGE support. 2 Copyright (C) 2001-2019 Free Software Foundation, Inc. 3 Written by Jakub Jelinek <jakub@redhat.com>. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 23 /* This file contains support for merging duplicate entities within sections, 24 as used in ELF SHF_MERGE. */ 25 26 #include "sysdep.h" 27 #include <limits.h> 28 #include "bfd.h" 29 #include "elf-bfd.h" 30 #include "libbfd.h" 31 #include "hashtab.h" 32 #include "libiberty.h" 33 34 struct sec_merge_sec_info; 35 36 /* An entry in the section merge hash table. */ 37 38 struct sec_merge_hash_entry 39 { 40 struct bfd_hash_entry root; 41 /* Length of this entry. This includes the zero terminator. */ 42 unsigned int len; 43 /* Start of this string needs to be aligned to 44 alignment octets (not 1 << align). */ 45 unsigned int alignment; 46 union 47 { 48 /* Index within the merged section. */ 49 bfd_size_type index; 50 /* Entry this is a suffix of (if alignment is 0). */ 51 struct sec_merge_hash_entry *suffix; 52 } u; 53 /* Which section is it in. */ 54 struct sec_merge_sec_info *secinfo; 55 /* Next entity in the hash table. */ 56 struct sec_merge_hash_entry *next; 57 }; 58 59 /* The section merge hash table. */ 60 61 struct sec_merge_hash 62 { 63 struct bfd_hash_table table; 64 /* Next available index. */ 65 bfd_size_type size; 66 /* First entity in the SEC_MERGE sections of this type. */ 67 struct sec_merge_hash_entry *first; 68 /* Last entity in the SEC_MERGE sections of this type. */ 69 struct sec_merge_hash_entry *last; 70 /* Entity size. */ 71 unsigned int entsize; 72 /* Are entries fixed size or zero terminated strings? */ 73 bfd_boolean strings; 74 }; 75 76 struct sec_merge_info 77 { 78 /* Chain of sec_merge_infos. */ 79 struct sec_merge_info *next; 80 /* Chain of sec_merge_sec_infos. */ 81 struct sec_merge_sec_info *chain; 82 /* A hash table used to hold section content. */ 83 struct sec_merge_hash *htab; 84 }; 85 86 struct sec_merge_sec_info 87 { 88 /* Chain of sec_merge_sec_infos. */ 89 struct sec_merge_sec_info *next; 90 /* The corresponding section. */ 91 asection *sec; 92 /* Pointer to merge_info pointing to us. */ 93 void **psecinfo; 94 /* A hash table used to hold section content. */ 95 struct sec_merge_hash *htab; 96 /* First string in this section. */ 97 struct sec_merge_hash_entry *first_str; 98 /* Original section content. */ 99 unsigned char contents[1]; 100 }; 101 102 103 /* Routine to create an entry in a section merge hashtab. */ 104 105 static struct bfd_hash_entry * 106 sec_merge_hash_newfunc (struct bfd_hash_entry *entry, 107 struct bfd_hash_table *table, const char *string) 108 { 109 /* Allocate the structure if it has not already been allocated by a 110 subclass. */ 111 if (entry == NULL) 112 entry = (struct bfd_hash_entry *) 113 bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry)); 114 if (entry == NULL) 115 return NULL; 116 117 /* Call the allocation method of the superclass. */ 118 entry = bfd_hash_newfunc (entry, table, string); 119 120 if (entry != NULL) 121 { 122 /* Initialize the local fields. */ 123 struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry; 124 125 ret->u.suffix = NULL; 126 ret->alignment = 0; 127 ret->secinfo = NULL; 128 ret->next = NULL; 129 } 130 131 return entry; 132 } 133 134 /* Look up an entry in a section merge hash table. */ 135 136 static struct sec_merge_hash_entry * 137 sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string, 138 unsigned int alignment, bfd_boolean create) 139 { 140 const unsigned char *s; 141 unsigned long hash; 142 unsigned int c; 143 struct sec_merge_hash_entry *hashp; 144 unsigned int len, i; 145 unsigned int _index; 146 147 hash = 0; 148 len = 0; 149 s = (const unsigned char *) string; 150 if (table->strings) 151 { 152 if (table->entsize == 1) 153 { 154 while ((c = *s++) != '\0') 155 { 156 hash += c + (c << 17); 157 hash ^= hash >> 2; 158 ++len; 159 } 160 hash += len + (len << 17); 161 } 162 else 163 { 164 for (;;) 165 { 166 for (i = 0; i < table->entsize; ++i) 167 if (s[i] != '\0') 168 break; 169 if (i == table->entsize) 170 break; 171 for (i = 0; i < table->entsize; ++i) 172 { 173 c = *s++; 174 hash += c + (c << 17); 175 hash ^= hash >> 2; 176 } 177 ++len; 178 } 179 hash += len + (len << 17); 180 len *= table->entsize; 181 } 182 hash ^= hash >> 2; 183 len += table->entsize; 184 } 185 else 186 { 187 for (i = 0; i < table->entsize; ++i) 188 { 189 c = *s++; 190 hash += c + (c << 17); 191 hash ^= hash >> 2; 192 } 193 len = table->entsize; 194 } 195 196 _index = hash % table->table.size; 197 for (hashp = (struct sec_merge_hash_entry *) table->table.table[_index]; 198 hashp != NULL; 199 hashp = (struct sec_merge_hash_entry *) hashp->root.next) 200 { 201 if (hashp->root.hash == hash 202 && len == hashp->len 203 && memcmp (hashp->root.string, string, len) == 0) 204 { 205 /* If the string we found does not have at least the required 206 alignment, we need to insert another copy. */ 207 if (hashp->alignment < alignment) 208 { 209 if (create) 210 { 211 /* Mark the less aligned copy as deleted. */ 212 hashp->len = 0; 213 hashp->alignment = 0; 214 } 215 break; 216 } 217 return hashp; 218 } 219 } 220 221 if (! create) 222 return NULL; 223 224 hashp = ((struct sec_merge_hash_entry *) 225 bfd_hash_insert (&table->table, string, hash)); 226 if (hashp == NULL) 227 return NULL; 228 hashp->len = len; 229 hashp->alignment = alignment; 230 return hashp; 231 } 232 233 /* Create a new hash table. */ 234 235 static struct sec_merge_hash * 236 sec_merge_init (unsigned int entsize, bfd_boolean strings) 237 { 238 struct sec_merge_hash *table; 239 240 table = (struct sec_merge_hash *) bfd_malloc (sizeof (struct sec_merge_hash)); 241 if (table == NULL) 242 return NULL; 243 244 if (! bfd_hash_table_init_n (&table->table, sec_merge_hash_newfunc, 245 sizeof (struct sec_merge_hash_entry), 16699)) 246 { 247 free (table); 248 return NULL; 249 } 250 251 table->size = 0; 252 table->first = NULL; 253 table->last = NULL; 254 table->entsize = entsize; 255 table->strings = strings; 256 257 return table; 258 } 259 260 /* Get the index of an entity in a hash table, adding it if it is not 261 already present. */ 262 263 static struct sec_merge_hash_entry * 264 sec_merge_add (struct sec_merge_hash *tab, const char *str, 265 unsigned int alignment, struct sec_merge_sec_info *secinfo) 266 { 267 struct sec_merge_hash_entry *entry; 268 269 entry = sec_merge_hash_lookup (tab, str, alignment, TRUE); 270 if (entry == NULL) 271 return NULL; 272 273 if (entry->secinfo == NULL) 274 { 275 tab->size++; 276 entry->secinfo = secinfo; 277 if (tab->first == NULL) 278 tab->first = entry; 279 else 280 tab->last->next = entry; 281 tab->last = entry; 282 } 283 284 return entry; 285 } 286 287 static bfd_boolean 288 sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry, 289 unsigned char *contents, file_ptr offset) 290 { 291 struct sec_merge_sec_info *secinfo = entry->secinfo; 292 asection *sec = secinfo->sec; 293 char *pad = NULL; 294 bfd_size_type off = 0; 295 int alignment_power = sec->output_section->alignment_power; 296 bfd_size_type pad_len; 297 298 /* FIXME: If alignment_power is 0 then really we should scan the 299 entry list for the largest required alignment and use that. */ 300 pad_len = alignment_power ? ((bfd_size_type) 1 << alignment_power) : 16; 301 302 pad = (char *) bfd_zmalloc (pad_len); 303 if (pad == NULL) 304 return FALSE; 305 306 for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next) 307 { 308 const char *str; 309 bfd_size_type len; 310 311 len = -off & (entry->alignment - 1); 312 if (len != 0) 313 { 314 BFD_ASSERT (len <= pad_len); 315 if (contents) 316 { 317 memcpy (contents + offset, pad, len); 318 offset += len; 319 } 320 else if (bfd_bwrite (pad, len, abfd) != len) 321 goto err; 322 off += len; 323 } 324 325 str = entry->root.string; 326 len = entry->len; 327 328 if (contents) 329 { 330 memcpy (contents + offset, str, len); 331 offset += len; 332 } 333 else if (bfd_bwrite (str, len, abfd) != len) 334 goto err; 335 336 off += len; 337 } 338 339 /* Trailing alignment needed? */ 340 off = sec->size - off; 341 if (pad != NULL && off != 0) 342 { 343 BFD_ASSERT (off <= pad_len); 344 if (contents) 345 memcpy (contents + offset, pad, off); 346 else if (bfd_bwrite (pad, off, abfd) != off) 347 goto err; 348 } 349 350 free (pad); 351 return TRUE; 352 353 err: 354 free (pad); 355 return FALSE; 356 } 357 358 /* Register a SEC_MERGE section as a candidate for merging. 359 This function is called for all non-dynamic SEC_MERGE input sections. */ 360 361 bfd_boolean 362 _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec, 363 void **psecinfo) 364 { 365 struct sec_merge_info *sinfo; 366 struct sec_merge_sec_info *secinfo; 367 unsigned int align; 368 bfd_size_type amt; 369 bfd_byte *contents; 370 371 if ((abfd->flags & DYNAMIC) != 0 372 || (sec->flags & SEC_MERGE) == 0) 373 abort (); 374 375 if (sec->size == 0 376 || (sec->flags & SEC_EXCLUDE) != 0 377 || sec->entsize == 0) 378 return TRUE; 379 380 if (sec->size % sec->entsize != 0) 381 return TRUE; 382 383 if ((sec->flags & SEC_RELOC) != 0) 384 { 385 /* We aren't prepared to handle relocations in merged sections. */ 386 return TRUE; 387 } 388 389 #ifndef CHAR_BIT 390 #define CHAR_BIT 8 391 #endif 392 if (sec->alignment_power >= sizeof (align) * CHAR_BIT) 393 return TRUE; 394 395 align = 1u << sec->alignment_power; 396 if ((sec->entsize < align 397 && ((sec->entsize & (sec->entsize - 1)) 398 || !(sec->flags & SEC_STRINGS))) 399 || (sec->entsize > align 400 && (sec->entsize & (align - 1)))) 401 { 402 /* Sanity check. If string character size is smaller than 403 alignment, then we require character size to be a power 404 of 2, otherwise character size must be integer multiple 405 of alignment. For non-string constants, alignment must 406 be smaller than or equal to entity size and entity size 407 must be integer multiple of alignment. */ 408 return TRUE; 409 } 410 411 for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next) 412 if ((secinfo = sinfo->chain) 413 && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS)) 414 && secinfo->sec->entsize == sec->entsize 415 && secinfo->sec->alignment_power == sec->alignment_power 416 && secinfo->sec->output_section == sec->output_section) 417 break; 418 419 if (sinfo == NULL) 420 { 421 /* Initialize the information we need to keep track of. */ 422 sinfo = (struct sec_merge_info *) 423 bfd_alloc (abfd, sizeof (struct sec_merge_info)); 424 if (sinfo == NULL) 425 goto error_return; 426 sinfo->next = (struct sec_merge_info *) *psinfo; 427 sinfo->chain = NULL; 428 *psinfo = sinfo; 429 sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS)); 430 if (sinfo->htab == NULL) 431 goto error_return; 432 } 433 434 /* Read the section from abfd. */ 435 436 amt = sizeof (struct sec_merge_sec_info) - 1 + sec->size; 437 if (sec->flags & SEC_STRINGS) 438 /* Some versions of gcc may emit a string without a zero terminator. 439 See http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01004.html 440 Allocate space for an extra zero. */ 441 amt += sec->entsize; 442 *psecinfo = bfd_alloc (abfd, amt); 443 if (*psecinfo == NULL) 444 goto error_return; 445 446 secinfo = (struct sec_merge_sec_info *) *psecinfo; 447 if (sinfo->chain) 448 { 449 secinfo->next = sinfo->chain->next; 450 sinfo->chain->next = secinfo; 451 } 452 else 453 secinfo->next = secinfo; 454 sinfo->chain = secinfo; 455 secinfo->sec = sec; 456 secinfo->psecinfo = psecinfo; 457 secinfo->htab = sinfo->htab; 458 secinfo->first_str = NULL; 459 460 sec->rawsize = sec->size; 461 if (sec->flags & SEC_STRINGS) 462 memset (secinfo->contents + sec->size, 0, sec->entsize); 463 contents = secinfo->contents; 464 if (! bfd_get_full_section_contents (sec->owner, sec, &contents)) 465 goto error_return; 466 467 return TRUE; 468 469 error_return: 470 *psecinfo = NULL; 471 return FALSE; 472 } 473 474 /* Record one section into the hash table. */ 475 static bfd_boolean 476 record_section (struct sec_merge_info *sinfo, 477 struct sec_merge_sec_info *secinfo) 478 { 479 asection *sec = secinfo->sec; 480 struct sec_merge_hash_entry *entry; 481 bfd_boolean nul; 482 unsigned char *p, *end; 483 bfd_vma mask, eltalign; 484 unsigned int align, i; 485 486 align = sec->alignment_power; 487 end = secinfo->contents + sec->size; 488 nul = FALSE; 489 mask = ((bfd_vma) 1 << align) - 1; 490 if (sec->flags & SEC_STRINGS) 491 { 492 for (p = secinfo->contents; p < end; ) 493 { 494 eltalign = p - secinfo->contents; 495 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1; 496 if (!eltalign || eltalign > mask) 497 eltalign = mask + 1; 498 entry = sec_merge_add (sinfo->htab, (char *) p, (unsigned) eltalign, 499 secinfo); 500 if (! entry) 501 goto error_return; 502 p += entry->len; 503 if (sec->entsize == 1) 504 { 505 while (p < end && *p == 0) 506 { 507 if (!nul && !((p - secinfo->contents) & mask)) 508 { 509 nul = TRUE; 510 entry = sec_merge_add (sinfo->htab, "", 511 (unsigned) mask + 1, secinfo); 512 if (! entry) 513 goto error_return; 514 } 515 p++; 516 } 517 } 518 else 519 { 520 while (p < end) 521 { 522 for (i = 0; i < sec->entsize; i++) 523 if (p[i] != '\0') 524 break; 525 if (i != sec->entsize) 526 break; 527 if (!nul && !((p - secinfo->contents) & mask)) 528 { 529 nul = TRUE; 530 entry = sec_merge_add (sinfo->htab, (char *) p, 531 (unsigned) mask + 1, secinfo); 532 if (! entry) 533 goto error_return; 534 } 535 p += sec->entsize; 536 } 537 } 538 } 539 } 540 else 541 { 542 for (p = secinfo->contents; p < end; p += sec->entsize) 543 { 544 entry = sec_merge_add (sinfo->htab, (char *) p, 1, secinfo); 545 if (! entry) 546 goto error_return; 547 } 548 } 549 550 return TRUE; 551 552 error_return: 553 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next) 554 *secinfo->psecinfo = NULL; 555 return FALSE; 556 } 557 558 static int 559 strrevcmp (const void *a, const void *b) 560 { 561 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a; 562 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b; 563 unsigned int lenA = A->len; 564 unsigned int lenB = B->len; 565 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1; 566 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1; 567 int l = lenA < lenB ? lenA : lenB; 568 569 while (l) 570 { 571 if (*s != *t) 572 return (int) *s - (int) *t; 573 s--; 574 t--; 575 l--; 576 } 577 return lenA - lenB; 578 } 579 580 /* Like strrevcmp, but for the case where all strings have the same 581 alignment > entsize. */ 582 583 static int 584 strrevcmp_align (const void *a, const void *b) 585 { 586 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a; 587 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b; 588 unsigned int lenA = A->len; 589 unsigned int lenB = B->len; 590 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1; 591 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1; 592 int l = lenA < lenB ? lenA : lenB; 593 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1)); 594 595 if (tail_align != 0) 596 return tail_align; 597 598 while (l) 599 { 600 if (*s != *t) 601 return (int) *s - (int) *t; 602 s--; 603 t--; 604 l--; 605 } 606 return lenA - lenB; 607 } 608 609 static inline int 610 is_suffix (const struct sec_merge_hash_entry *A, 611 const struct sec_merge_hash_entry *B) 612 { 613 if (A->len <= B->len) 614 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed 615 not to be equal by the hash table. */ 616 return 0; 617 618 return memcmp (A->root.string + (A->len - B->len), 619 B->root.string, B->len) == 0; 620 } 621 622 /* This is a helper function for _bfd_merge_sections. It attempts to 623 merge strings matching suffixes of longer strings. */ 624 static bfd_boolean 625 merge_strings (struct sec_merge_info *sinfo) 626 { 627 struct sec_merge_hash_entry **array, **a, *e; 628 struct sec_merge_sec_info *secinfo; 629 bfd_size_type size, amt; 630 unsigned int alignment = 0; 631 632 /* Now sort the strings */ 633 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *); 634 array = (struct sec_merge_hash_entry **) bfd_malloc (amt); 635 if (array == NULL) 636 return FALSE; 637 638 for (e = sinfo->htab->first, a = array; e; e = e->next) 639 if (e->alignment) 640 { 641 *a++ = e; 642 /* Adjust the length to not include the zero terminator. */ 643 e->len -= sinfo->htab->entsize; 644 if (alignment != e->alignment) 645 { 646 if (alignment == 0) 647 alignment = e->alignment; 648 else 649 alignment = (unsigned) -1; 650 } 651 } 652 653 sinfo->htab->size = a - array; 654 if (sinfo->htab->size != 0) 655 { 656 qsort (array, (size_t) sinfo->htab->size, 657 sizeof (struct sec_merge_hash_entry *), 658 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize 659 ? strrevcmp_align : strrevcmp)); 660 661 /* Loop over the sorted array and merge suffixes */ 662 e = *--a; 663 e->len += sinfo->htab->entsize; 664 while (--a >= array) 665 { 666 struct sec_merge_hash_entry *cmp = *a; 667 668 cmp->len += sinfo->htab->entsize; 669 if (e->alignment >= cmp->alignment 670 && !((e->len - cmp->len) & (cmp->alignment - 1)) 671 && is_suffix (e, cmp)) 672 { 673 cmp->u.suffix = e; 674 cmp->alignment = 0; 675 } 676 else 677 e = cmp; 678 } 679 } 680 681 free (array); 682 683 /* Now assign positions to the strings we want to keep. */ 684 size = 0; 685 secinfo = sinfo->htab->first->secinfo; 686 for (e = sinfo->htab->first; e; e = e->next) 687 { 688 if (e->secinfo != secinfo) 689 { 690 secinfo->sec->size = size; 691 secinfo = e->secinfo; 692 } 693 if (e->alignment) 694 { 695 if (e->secinfo->first_str == NULL) 696 { 697 e->secinfo->first_str = e; 698 size = 0; 699 } 700 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1); 701 e->u.index = size; 702 size += e->len; 703 } 704 } 705 secinfo->sec->size = size; 706 if (secinfo->sec->alignment_power != 0) 707 { 708 bfd_size_type align = (bfd_size_type) 1 << secinfo->sec->alignment_power; 709 secinfo->sec->size = (secinfo->sec->size + align - 1) & -align; 710 } 711 712 /* And now adjust the rest, removing them from the chain (but not hashtable) 713 at the same time. */ 714 for (a = &sinfo->htab->first, e = *a; e; e = e->next) 715 if (e->alignment) 716 a = &e->next; 717 else 718 { 719 *a = e->next; 720 if (e->len) 721 { 722 e->secinfo = e->u.suffix->secinfo; 723 e->alignment = e->u.suffix->alignment; 724 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len); 725 } 726 } 727 return TRUE; 728 } 729 730 /* This function is called once after all SEC_MERGE sections are registered 731 with _bfd_merge_section. */ 732 733 bfd_boolean 734 _bfd_merge_sections (bfd *abfd, 735 struct bfd_link_info *info ATTRIBUTE_UNUSED, 736 void *xsinfo, 737 void (*remove_hook) (bfd *, asection *)) 738 { 739 struct sec_merge_info *sinfo; 740 741 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) 742 { 743 struct sec_merge_sec_info * secinfo; 744 745 if (! sinfo->chain) 746 continue; 747 748 /* Move sinfo->chain to head of the chain, terminate it. */ 749 secinfo = sinfo->chain; 750 sinfo->chain = secinfo->next; 751 secinfo->next = NULL; 752 753 /* Record the sections into the hash table. */ 754 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next) 755 if (secinfo->sec->flags & SEC_EXCLUDE) 756 { 757 *secinfo->psecinfo = NULL; 758 if (remove_hook) 759 (*remove_hook) (abfd, secinfo->sec); 760 } 761 else if (! record_section (sinfo, secinfo)) 762 return FALSE; 763 764 if (secinfo) 765 continue; 766 767 if (sinfo->htab->first == NULL) 768 continue; 769 770 if (sinfo->htab->strings) 771 { 772 if (!merge_strings (sinfo)) 773 return FALSE; 774 } 775 else 776 { 777 struct sec_merge_hash_entry *e; 778 bfd_size_type size = 0; 779 780 /* Things are much simpler for non-strings. 781 Just assign them slots in the section. */ 782 secinfo = NULL; 783 for (e = sinfo->htab->first; e; e = e->next) 784 { 785 if (e->secinfo->first_str == NULL) 786 { 787 if (secinfo) 788 secinfo->sec->size = size; 789 e->secinfo->first_str = e; 790 size = 0; 791 } 792 size = (size + e->alignment - 1) 793 & ~((bfd_vma) e->alignment - 1); 794 e->u.index = size; 795 size += e->len; 796 secinfo = e->secinfo; 797 } 798 secinfo->sec->size = size; 799 } 800 801 /* Finally remove all input sections which have not made it into 802 the hash table at all. */ 803 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next) 804 if (secinfo->first_str == NULL) 805 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP; 806 } 807 808 return TRUE; 809 } 810 811 /* Write out the merged section. */ 812 813 bfd_boolean 814 _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) 815 { 816 struct sec_merge_sec_info *secinfo; 817 file_ptr pos; 818 unsigned char *contents; 819 Elf_Internal_Shdr *hdr; 820 821 secinfo = (struct sec_merge_sec_info *) psecinfo; 822 823 if (!secinfo) 824 return FALSE; 825 826 if (secinfo->first_str == NULL) 827 return TRUE; 828 829 /* FIXME: octets_per_byte. */ 830 hdr = &elf_section_data (sec->output_section)->this_hdr; 831 if (hdr->sh_offset == (file_ptr) -1) 832 { 833 /* We must compress this section. Write output to the 834 buffer. */ 835 contents = hdr->contents; 836 if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0 837 || contents == NULL) 838 abort (); 839 } 840 else 841 { 842 contents = NULL; 843 pos = sec->output_section->filepos + sec->output_offset; 844 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) 845 return FALSE; 846 } 847 848 if (! sec_merge_emit (output_bfd, secinfo->first_str, contents, 849 sec->output_offset)) 850 return FALSE; 851 852 return TRUE; 853 } 854 855 /* Adjust an address in the SEC_MERGE section. Given OFFSET within 856 *PSEC, this returns the new offset in the adjusted SEC_MERGE 857 section and writes the new section back into *PSEC. */ 858 859 bfd_vma 860 _bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec, 861 void *psecinfo, bfd_vma offset) 862 { 863 struct sec_merge_sec_info *secinfo; 864 struct sec_merge_hash_entry *entry; 865 unsigned char *p; 866 asection *sec = *psec; 867 868 secinfo = (struct sec_merge_sec_info *) psecinfo; 869 870 if (!secinfo) 871 return offset; 872 873 if (offset >= sec->rawsize) 874 { 875 if (offset > sec->rawsize) 876 _bfd_error_handler 877 /* xgettext:c-format */ 878 (_("%pB: access beyond end of merged section (%" PRId64 ")"), 879 sec->owner, (int64_t) offset); 880 return secinfo->first_str ? sec->size : 0; 881 } 882 883 if (secinfo->htab->strings) 884 { 885 if (sec->entsize == 1) 886 { 887 p = secinfo->contents + offset - 1; 888 while (p >= secinfo->contents && *p) 889 --p; 890 ++p; 891 } 892 else 893 { 894 p = secinfo->contents + (offset / sec->entsize) * sec->entsize; 895 p -= sec->entsize; 896 while (p >= secinfo->contents) 897 { 898 unsigned int i; 899 900 for (i = 0; i < sec->entsize; ++i) 901 if (p[i] != '\0') 902 break; 903 if (i == sec->entsize) 904 break; 905 p -= sec->entsize; 906 } 907 p += sec->entsize; 908 } 909 } 910 else 911 { 912 p = secinfo->contents + (offset / sec->entsize) * sec->entsize; 913 } 914 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE); 915 if (!entry) 916 { 917 if (! secinfo->htab->strings) 918 abort (); 919 /* This should only happen if somebody points into the padding 920 after a NUL character but before next entity. */ 921 if (*p) 922 abort (); 923 if (! secinfo->htab->first) 924 abort (); 925 entry = secinfo->htab->first; 926 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize 927 - entry->len); 928 } 929 930 *psec = entry->secinfo->sec; 931 return entry->u.index + (secinfo->contents + offset - p); 932 } 933 934 /* Tidy up when done. */ 935 936 void 937 _bfd_merge_sections_free (void *xsinfo) 938 { 939 struct sec_merge_info *sinfo; 940 941 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) 942 { 943 bfd_hash_table_free (&sinfo->htab->table); 944 free (sinfo->htab); 945 } 946 } 947