1 /* SEC_MERGE support. 2 Copyright (C) 2001-2020 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 (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 /* qsort comparison function. Won't ever return zero as all entries 559 differ, so there is no issue with qsort stability here. */ 560 561 static int 562 strrevcmp (const void *a, const void *b) 563 { 564 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a; 565 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b; 566 unsigned int lenA = A->len; 567 unsigned int lenB = B->len; 568 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1; 569 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1; 570 int l = lenA < lenB ? lenA : lenB; 571 572 while (l) 573 { 574 if (*s != *t) 575 return (int) *s - (int) *t; 576 s--; 577 t--; 578 l--; 579 } 580 return lenA - lenB; 581 } 582 583 /* Like strrevcmp, but for the case where all strings have the same 584 alignment > entsize. */ 585 586 static int 587 strrevcmp_align (const void *a, const void *b) 588 { 589 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a; 590 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b; 591 unsigned int lenA = A->len; 592 unsigned int lenB = B->len; 593 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1; 594 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1; 595 int l = lenA < lenB ? lenA : lenB; 596 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1)); 597 598 if (tail_align != 0) 599 return tail_align; 600 601 while (l) 602 { 603 if (*s != *t) 604 return (int) *s - (int) *t; 605 s--; 606 t--; 607 l--; 608 } 609 return lenA - lenB; 610 } 611 612 static inline int 613 is_suffix (const struct sec_merge_hash_entry *A, 614 const struct sec_merge_hash_entry *B) 615 { 616 if (A->len <= B->len) 617 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed 618 not to be equal by the hash table. */ 619 return 0; 620 621 return memcmp (A->root.string + (A->len - B->len), 622 B->root.string, B->len) == 0; 623 } 624 625 /* This is a helper function for _bfd_merge_sections. It attempts to 626 merge strings matching suffixes of longer strings. */ 627 static struct sec_merge_sec_info * 628 merge_strings (struct sec_merge_info *sinfo) 629 { 630 struct sec_merge_hash_entry **array, **a, *e; 631 struct sec_merge_sec_info *secinfo; 632 bfd_size_type size, amt; 633 unsigned int alignment = 0; 634 635 /* Now sort the strings */ 636 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *); 637 array = (struct sec_merge_hash_entry **) bfd_malloc (amt); 638 if (array == NULL) 639 return NULL; 640 641 for (e = sinfo->htab->first, a = array; e; e = e->next) 642 if (e->alignment) 643 { 644 *a++ = e; 645 /* Adjust the length to not include the zero terminator. */ 646 e->len -= sinfo->htab->entsize; 647 if (alignment != e->alignment) 648 { 649 if (alignment == 0) 650 alignment = e->alignment; 651 else 652 alignment = (unsigned) -1; 653 } 654 } 655 656 sinfo->htab->size = a - array; 657 if (sinfo->htab->size != 0) 658 { 659 qsort (array, (size_t) sinfo->htab->size, 660 sizeof (struct sec_merge_hash_entry *), 661 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize 662 ? strrevcmp_align : strrevcmp)); 663 664 /* Loop over the sorted array and merge suffixes */ 665 e = *--a; 666 e->len += sinfo->htab->entsize; 667 while (--a >= array) 668 { 669 struct sec_merge_hash_entry *cmp = *a; 670 671 cmp->len += sinfo->htab->entsize; 672 if (e->alignment >= cmp->alignment 673 && !((e->len - cmp->len) & (cmp->alignment - 1)) 674 && is_suffix (e, cmp)) 675 { 676 cmp->u.suffix = e; 677 cmp->alignment = 0; 678 } 679 else 680 e = cmp; 681 } 682 } 683 684 free (array); 685 686 /* Now assign positions to the strings we want to keep. */ 687 size = 0; 688 secinfo = sinfo->htab->first->secinfo; 689 for (e = sinfo->htab->first; e; e = e->next) 690 { 691 if (e->secinfo != secinfo) 692 { 693 secinfo->sec->size = size; 694 secinfo = e->secinfo; 695 } 696 if (e->alignment) 697 { 698 if (e->secinfo->first_str == NULL) 699 { 700 e->secinfo->first_str = e; 701 size = 0; 702 } 703 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1); 704 e->u.index = size; 705 size += e->len; 706 } 707 } 708 secinfo->sec->size = size; 709 710 /* And now adjust the rest, removing them from the chain (but not hashtable) 711 at the same time. */ 712 for (a = &sinfo->htab->first, e = *a; e; e = e->next) 713 if (e->alignment) 714 a = &e->next; 715 else 716 { 717 *a = e->next; 718 if (e->len) 719 { 720 e->secinfo = e->u.suffix->secinfo; 721 e->alignment = e->u.suffix->alignment; 722 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len); 723 } 724 } 725 return secinfo; 726 } 727 728 /* This function is called once after all SEC_MERGE sections are registered 729 with _bfd_merge_section. */ 730 731 bfd_boolean 732 _bfd_merge_sections (bfd *abfd, 733 struct bfd_link_info *info ATTRIBUTE_UNUSED, 734 void *xsinfo, 735 void (*remove_hook) (bfd *, asection *)) 736 { 737 struct sec_merge_info *sinfo; 738 739 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) 740 { 741 struct sec_merge_sec_info *secinfo; 742 bfd_size_type align; 743 744 if (! sinfo->chain) 745 continue; 746 747 /* Move sinfo->chain to head of the chain, terminate it. */ 748 secinfo = sinfo->chain; 749 sinfo->chain = secinfo->next; 750 secinfo->next = NULL; 751 752 /* Record the sections into the hash table. */ 753 align = 1; 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 762 { 763 if (!record_section (sinfo, secinfo)) 764 return FALSE; 765 if (align) 766 { 767 align = (bfd_size_type) 1 << secinfo->sec->alignment_power; 768 if ((secinfo->sec->size & (align - 1)) != 0) 769 align = 0; 770 } 771 } 772 773 if (sinfo->htab->first == NULL) 774 continue; 775 776 if (sinfo->htab->strings) 777 { 778 secinfo = merge_strings (sinfo); 779 if (!secinfo) 780 return FALSE; 781 } 782 else 783 { 784 struct sec_merge_hash_entry *e; 785 bfd_size_type size = 0; 786 787 /* Things are much simpler for non-strings. 788 Just assign them slots in the section. */ 789 secinfo = NULL; 790 for (e = sinfo->htab->first; e; e = e->next) 791 { 792 if (e->secinfo->first_str == NULL) 793 { 794 if (secinfo) 795 secinfo->sec->size = size; 796 e->secinfo->first_str = e; 797 size = 0; 798 } 799 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1); 800 e->u.index = size; 801 size += e->len; 802 secinfo = e->secinfo; 803 } 804 secinfo->sec->size = size; 805 } 806 807 /* If the input sections were padded according to their alignments, 808 then pad the output too. */ 809 if (align) 810 secinfo->sec->size = (secinfo->sec->size + align - 1) & -align; 811 812 /* Finally remove all input sections which have not made it into 813 the hash table at all. */ 814 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next) 815 if (secinfo->first_str == NULL) 816 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP; 817 } 818 819 return TRUE; 820 } 821 822 /* Write out the merged section. */ 823 824 bfd_boolean 825 _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) 826 { 827 struct sec_merge_sec_info *secinfo; 828 file_ptr pos; 829 unsigned char *contents; 830 Elf_Internal_Shdr *hdr; 831 832 secinfo = (struct sec_merge_sec_info *) psecinfo; 833 834 if (!secinfo) 835 return FALSE; 836 837 if (secinfo->first_str == NULL) 838 return TRUE; 839 840 /* FIXME: octets_per_byte. */ 841 hdr = &elf_section_data (sec->output_section)->this_hdr; 842 if (hdr->sh_offset == (file_ptr) -1) 843 { 844 /* We must compress this section. Write output to the 845 buffer. */ 846 contents = hdr->contents; 847 if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0 848 || contents == NULL) 849 abort (); 850 } 851 else 852 { 853 contents = NULL; 854 pos = sec->output_section->filepos + sec->output_offset; 855 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) 856 return FALSE; 857 } 858 859 if (! sec_merge_emit (output_bfd, secinfo->first_str, contents, 860 sec->output_offset)) 861 return FALSE; 862 863 return TRUE; 864 } 865 866 /* Adjust an address in the SEC_MERGE section. Given OFFSET within 867 *PSEC, this returns the new offset in the adjusted SEC_MERGE 868 section and writes the new section back into *PSEC. */ 869 870 bfd_vma 871 _bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec, 872 void *psecinfo, bfd_vma offset) 873 { 874 struct sec_merge_sec_info *secinfo; 875 struct sec_merge_hash_entry *entry; 876 unsigned char *p; 877 asection *sec = *psec; 878 879 secinfo = (struct sec_merge_sec_info *) psecinfo; 880 881 if (!secinfo) 882 return offset; 883 884 if (offset >= sec->rawsize) 885 { 886 if (offset > sec->rawsize) 887 _bfd_error_handler 888 /* xgettext:c-format */ 889 (_("%pB: access beyond end of merged section (%" PRId64 ")"), 890 sec->owner, (int64_t) offset); 891 return secinfo->first_str ? sec->size : 0; 892 } 893 894 if (secinfo->htab->strings) 895 { 896 if (sec->entsize == 1) 897 { 898 p = secinfo->contents + offset - 1; 899 while (p >= secinfo->contents && *p) 900 --p; 901 ++p; 902 } 903 else 904 { 905 p = secinfo->contents + (offset / sec->entsize) * sec->entsize; 906 p -= sec->entsize; 907 while (p >= secinfo->contents) 908 { 909 unsigned int i; 910 911 for (i = 0; i < sec->entsize; ++i) 912 if (p[i] != '\0') 913 break; 914 if (i == sec->entsize) 915 break; 916 p -= sec->entsize; 917 } 918 p += sec->entsize; 919 } 920 } 921 else 922 { 923 p = secinfo->contents + (offset / sec->entsize) * sec->entsize; 924 } 925 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE); 926 if (!entry) 927 { 928 if (! secinfo->htab->strings) 929 abort (); 930 /* This should only happen if somebody points into the padding 931 after a NUL character but before next entity. */ 932 if (*p) 933 abort (); 934 if (! secinfo->htab->first) 935 abort (); 936 entry = secinfo->htab->first; 937 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize 938 - entry->len); 939 } 940 941 *psec = entry->secinfo->sec; 942 return entry->u.index + (secinfo->contents + offset - p); 943 } 944 945 /* Tidy up when done. */ 946 947 void 948 _bfd_merge_sections_free (void *xsinfo) 949 { 950 struct sec_merge_info *sinfo; 951 952 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next) 953 { 954 bfd_hash_table_free (&sinfo->htab->table); 955 free (sinfo->htab); 956 } 957 } 958