1 /* ELF program property support. 2 Copyright (C) 2017-2022 Free Software Foundation, Inc. 3 4 This file is part of BFD, the Binary File Descriptor library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 /* GNU program property draft is at: 22 23 https://github.com/hjl-tools/linux-abi/wiki/property-draft.pdf 24 */ 25 26 #include "sysdep.h" 27 #include "bfd.h" 28 #include "libbfd.h" 29 #include "elf-bfd.h" 30 31 /* Get a property, allocate a new one if needed. */ 32 33 elf_property * 34 _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz) 35 { 36 elf_property_list *p, **lastp; 37 38 if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) 39 { 40 /* Never should happen. */ 41 abort (); 42 } 43 44 /* Keep the property list in order of type. */ 45 lastp = &elf_properties (abfd); 46 for (p = *lastp; p; p = p->next) 47 { 48 /* Reuse the existing entry. */ 49 if (type == p->property.pr_type) 50 { 51 if (datasz > p->property.pr_datasz) 52 { 53 /* This can happen when mixing 32-bit and 64-bit objects. */ 54 p->property.pr_datasz = datasz; 55 } 56 return &p->property; 57 } 58 else if (type < p->property.pr_type) 59 break; 60 lastp = &p->next; 61 } 62 p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p)); 63 if (p == NULL) 64 { 65 _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"), 66 abfd); 67 _exit (EXIT_FAILURE); 68 } 69 memset (p, 0, sizeof (*p)); 70 p->property.pr_type = type; 71 p->property.pr_datasz = datasz; 72 p->next = *lastp; 73 *lastp = p; 74 return &p->property; 75 } 76 77 /* Parse GNU properties. */ 78 79 bool 80 _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note) 81 { 82 const struct elf_backend_data *bed = get_elf_backend_data (abfd); 83 unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4; 84 bfd_byte *ptr = (bfd_byte *) note->descdata; 85 bfd_byte *ptr_end = ptr + note->descsz; 86 87 if (note->descsz < 8 || (note->descsz % align_size) != 0) 88 { 89 bad_size: 90 _bfd_error_handler 91 (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"), 92 abfd, note->type, note->descsz); 93 return false; 94 } 95 96 while (ptr != ptr_end) 97 { 98 unsigned int type; 99 unsigned int datasz; 100 elf_property *prop; 101 102 if ((size_t) (ptr_end - ptr) < 8) 103 goto bad_size; 104 105 type = bfd_h_get_32 (abfd, ptr); 106 datasz = bfd_h_get_32 (abfd, ptr + 4); 107 ptr += 8; 108 109 if (datasz > (size_t) (ptr_end - ptr)) 110 { 111 _bfd_error_handler 112 (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"), 113 abfd, note->type, type, datasz); 114 /* Clear all properties. */ 115 elf_properties (abfd) = NULL; 116 return false; 117 } 118 119 if (type >= GNU_PROPERTY_LOPROC) 120 { 121 if (bed->elf_machine_code == EM_NONE) 122 { 123 /* Ignore processor-specific properties with generic ELF 124 target vector. They should be handled by the matching 125 ELF target vector. */ 126 goto next; 127 } 128 else if (type < GNU_PROPERTY_LOUSER 129 && bed->parse_gnu_properties) 130 { 131 enum elf_property_kind kind 132 = bed->parse_gnu_properties (abfd, type, ptr, datasz); 133 if (kind == property_corrupt) 134 { 135 /* Clear all properties. */ 136 elf_properties (abfd) = NULL; 137 return false; 138 } 139 else if (kind != property_ignored) 140 goto next; 141 } 142 } 143 else 144 { 145 switch (type) 146 { 147 case GNU_PROPERTY_STACK_SIZE: 148 if (datasz != align_size) 149 { 150 _bfd_error_handler 151 (_("warning: %pB: corrupt stack size: 0x%x"), 152 abfd, datasz); 153 /* Clear all properties. */ 154 elf_properties (abfd) = NULL; 155 return false; 156 } 157 prop = _bfd_elf_get_property (abfd, type, datasz); 158 if (datasz == 8) 159 prop->u.number = bfd_h_get_64 (abfd, ptr); 160 else 161 prop->u.number = bfd_h_get_32 (abfd, ptr); 162 prop->pr_kind = property_number; 163 goto next; 164 165 case GNU_PROPERTY_NO_COPY_ON_PROTECTED: 166 if (datasz != 0) 167 { 168 _bfd_error_handler 169 (_("warning: %pB: corrupt no copy on protected size: 0x%x"), 170 abfd, datasz); 171 /* Clear all properties. */ 172 elf_properties (abfd) = NULL; 173 return false; 174 } 175 prop = _bfd_elf_get_property (abfd, type, datasz); 176 elf_has_no_copy_on_protected (abfd) = true; 177 prop->pr_kind = property_number; 178 goto next; 179 180 default: 181 if ((type >= GNU_PROPERTY_UINT32_AND_LO 182 && type <= GNU_PROPERTY_UINT32_AND_HI) 183 || (type >= GNU_PROPERTY_UINT32_OR_LO 184 && type <= GNU_PROPERTY_UINT32_OR_HI)) 185 { 186 if (datasz != 4) 187 { 188 _bfd_error_handler 189 (_("error: %pB: <corrupt property (0x%x) size: 0x%x>"), 190 abfd, type, datasz); 191 /* Clear all properties. */ 192 elf_properties (abfd) = NULL; 193 return false; 194 } 195 prop = _bfd_elf_get_property (abfd, type, datasz); 196 prop->u.number |= bfd_h_get_32 (abfd, ptr); 197 prop->pr_kind = property_number; 198 if (type == GNU_PROPERTY_1_NEEDED 199 && ((prop->u.number 200 & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) 201 != 0)) 202 { 203 elf_has_indirect_extern_access (abfd) = true; 204 /* GNU_PROPERTY_NO_COPY_ON_PROTECTED is implied. */ 205 elf_has_no_copy_on_protected (abfd) = true; 206 } 207 goto next; 208 } 209 break; 210 } 211 } 212 213 _bfd_error_handler 214 (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"), 215 abfd, note->type, type); 216 217 next: 218 ptr += (datasz + (align_size - 1)) & ~ (align_size - 1); 219 } 220 221 return true; 222 } 223 224 /* Merge GNU property BPROP with APROP. If APROP isn't NULL, return TRUE 225 if APROP is updated. Otherwise, return TRUE if BPROP should be merged 226 with ABFD. */ 227 228 static bool 229 elf_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, bfd *bbfd, 230 elf_property *aprop, elf_property *bprop) 231 { 232 const struct elf_backend_data *bed = get_elf_backend_data (abfd); 233 unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type; 234 unsigned int number; 235 bool updated; 236 237 if (bed->merge_gnu_properties != NULL 238 && pr_type >= GNU_PROPERTY_LOPROC 239 && pr_type < GNU_PROPERTY_LOUSER) 240 return bed->merge_gnu_properties (info, abfd, bbfd, aprop, bprop); 241 242 switch (pr_type) 243 { 244 case GNU_PROPERTY_STACK_SIZE: 245 if (aprop != NULL && bprop != NULL) 246 { 247 if (bprop->u.number > aprop->u.number) 248 { 249 aprop->u.number = bprop->u.number; 250 return true; 251 } 252 break; 253 } 254 /* FALLTHROUGH */ 255 256 case GNU_PROPERTY_NO_COPY_ON_PROTECTED: 257 /* Return TRUE if APROP is NULL to indicate that BPROP should 258 be added to ABFD. */ 259 return aprop == NULL; 260 261 default: 262 updated = false; 263 if (pr_type >= GNU_PROPERTY_UINT32_OR_LO 264 && pr_type <= GNU_PROPERTY_UINT32_OR_HI) 265 { 266 if (aprop != NULL && bprop != NULL) 267 { 268 number = aprop->u.number; 269 aprop->u.number = number | bprop->u.number; 270 /* Remove the property if all bits are empty. */ 271 if (aprop->u.number == 0) 272 { 273 aprop->pr_kind = property_remove; 274 updated = true; 275 } 276 else 277 updated = number != (unsigned int) aprop->u.number; 278 } 279 else 280 { 281 /* Only one of APROP and BPROP can be NULL. */ 282 if (aprop != NULL) 283 { 284 if (aprop->u.number == 0) 285 { 286 /* Remove APROP if all bits are empty. */ 287 aprop->pr_kind = property_remove; 288 updated = true; 289 } 290 } 291 else 292 { 293 /* Return TRUE if APROP is NULL and all bits of BPROP 294 aren't empty to indicate that BPROP should be added 295 to ABFD. */ 296 updated = bprop->u.number != 0; 297 } 298 } 299 return updated; 300 } 301 else if (pr_type >= GNU_PROPERTY_UINT32_AND_LO 302 && pr_type <= GNU_PROPERTY_UINT32_AND_HI) 303 { 304 /* Only one of APROP and BPROP can be NULL: 305 1. APROP & BPROP when both APROP and BPROP aren't NULL. 306 2. If APROP is NULL, remove x86 feature. 307 3. Otherwise, do nothing. 308 */ 309 if (aprop != NULL && bprop != NULL) 310 { 311 number = aprop->u.number; 312 aprop->u.number = number & bprop->u.number; 313 updated = number != (unsigned int) aprop->u.number; 314 /* Remove the property if all feature bits are cleared. */ 315 if (aprop->u.number == 0) 316 aprop->pr_kind = property_remove; 317 } 318 else 319 { 320 /* There should be no AND properties since some input 321 doesn't have them. */ 322 if (aprop != NULL) 323 { 324 aprop->pr_kind = property_remove; 325 updated = true; 326 } 327 } 328 return updated; 329 } 330 331 /* Never should happen. */ 332 abort (); 333 } 334 335 return false; 336 } 337 338 /* Return the property of TYPE on *LISTP and remove it from *LISTP if RM is 339 true. Return NULL if not found. */ 340 341 static elf_property * 342 elf_find_and_remove_property (elf_property_list **listp, 343 unsigned int type, bool rm) 344 { 345 elf_property_list *list; 346 347 for (list = *listp; list; list = list->next) 348 { 349 if (type == list->property.pr_type) 350 { 351 /* Remove this property. */ 352 if (rm) 353 *listp = list->next; 354 return &list->property; 355 } 356 else if (type < list->property.pr_type) 357 break; 358 listp = &list->next; 359 } 360 361 return NULL; 362 } 363 364 /* Merge GNU property list *LISTP in ABFD with FIRST_PBFD. */ 365 366 static void 367 elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *first_pbfd, 368 bfd *abfd, elf_property_list **listp) 369 { 370 elf_property_list *p, **lastp; 371 elf_property *pr; 372 bool number_p; 373 bfd_vma number = 0; 374 375 /* Merge each GNU property in FIRST_PBFD with the one on *LISTP. */ 376 lastp = &elf_properties (first_pbfd); 377 for (p = *lastp; p; p = p->next) 378 if (p->property.pr_kind != property_remove) 379 { 380 if (p->property.pr_kind == property_number) 381 { 382 number_p = true; 383 number = p->property.u.number; 384 } 385 else 386 number_p = false; 387 pr = elf_find_and_remove_property (listp, p->property.pr_type, 388 true); 389 /* Pass NULL to elf_merge_gnu_properties for the property which 390 isn't on *LISTP. */ 391 elf_merge_gnu_properties (info, first_pbfd, abfd, &p->property, pr); 392 if (p->property.pr_kind == property_remove) 393 { 394 if (info->has_map_file) 395 { 396 if (number_p) 397 { 398 if (pr != NULL) 399 info->callbacks->minfo 400 (_("Removed property %W to merge %pB (0x%v) " 401 "and %pB (0x%v)\n"), 402 (bfd_vma) p->property.pr_type, first_pbfd, 403 number, abfd, pr->u.number); 404 else 405 info->callbacks->minfo 406 (_("Removed property %W to merge %pB (0x%v) " 407 "and %pB (not found)\n"), 408 (bfd_vma) p->property.pr_type, first_pbfd, 409 number, abfd); 410 } 411 else 412 { 413 if (pr != NULL) 414 info->callbacks->minfo 415 (_("Removed property %W to merge %pB and %pB\n"), 416 (bfd_vma) p->property.pr_type, first_pbfd, abfd); 417 else 418 info->callbacks->minfo 419 (_("Removed property %W to merge %pB and %pB " 420 "(not found)\n"), 421 (bfd_vma) p->property.pr_type, first_pbfd, abfd); 422 } 423 } 424 425 /* Remove this property. */ 426 *lastp = p->next; 427 continue; 428 } 429 else if (number_p) 430 { 431 if (pr != NULL) 432 { 433 if (p->property.u.number != number 434 || p->property.u.number != pr->u.number) 435 info->callbacks->minfo 436 (_("Updated property %W (0x%v) to merge %pB (0x%v) " 437 "and %pB (0x%v)\n"), 438 (bfd_vma) p->property.pr_type, p->property.u.number, 439 first_pbfd, number, abfd, pr->u.number); 440 } 441 else 442 { 443 if (p->property.u.number != number) 444 info->callbacks->minfo 445 (_("Updated property %W (%v) to merge %pB (0x%v) " 446 "and %pB (not found)\n"), 447 (bfd_vma) p->property.pr_type, p->property.u.number, 448 first_pbfd, number, abfd); 449 } 450 } 451 lastp = &p->next; 452 } 453 454 /* Merge the remaining properties on *LISTP with FIRST_PBFD. */ 455 for (p = *listp; p != NULL; p = p->next) 456 { 457 if (p->property.pr_kind == property_number) 458 { 459 number_p = true; 460 number = p->property.u.number; 461 } 462 else 463 number_p = false; 464 465 if (elf_merge_gnu_properties (info, first_pbfd, abfd, NULL, &p->property)) 466 { 467 if (p->property.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED) 468 elf_has_no_copy_on_protected (first_pbfd) = true; 469 470 pr = _bfd_elf_get_property (first_pbfd, p->property.pr_type, 471 p->property.pr_datasz); 472 /* It must be a new property. */ 473 if (pr->pr_kind != property_unknown) 474 abort (); 475 /* Add a new property. */ 476 *pr = p->property; 477 } 478 else 479 { 480 pr = elf_find_and_remove_property (&elf_properties (first_pbfd), 481 p->property.pr_type, 482 false); 483 if (pr == NULL) 484 { 485 if (number_p) 486 info->callbacks->minfo 487 (_("Removed property %W to merge %pB (not found) and " 488 "%pB (0x%v)\n"), 489 (bfd_vma) p->property.pr_type, first_pbfd, abfd, 490 number); 491 else 492 info->callbacks->minfo 493 (_("Removed property %W to merge %pB and %pB\n"), 494 (bfd_vma) p->property.pr_type, first_pbfd, abfd); 495 } 496 else if (pr->pr_kind != property_remove) 497 abort (); 498 } 499 } 500 } 501 502 /* Get GNU property section size. */ 503 504 static bfd_size_type 505 elf_get_gnu_property_section_size (elf_property_list *list, 506 unsigned int align_size) 507 { 508 bfd_size_type size; 509 unsigned int descsz; 510 511 /* Compute the output section size. */ 512 descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]); 513 descsz = (descsz + 3) & -(unsigned int) 4; 514 size = descsz; 515 for (; list != NULL; list = list->next) 516 { 517 unsigned int datasz; 518 /* Check if this property should be skipped. */ 519 if (list->property.pr_kind == property_remove) 520 continue; 521 /* There are 4 byte type + 4 byte datasz for each property. */ 522 if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE) 523 datasz = align_size; 524 else 525 datasz = list->property.pr_datasz; 526 size += 4 + 4 + datasz; 527 /* Align each property. */ 528 size = (size + (align_size - 1)) & ~(align_size - 1); 529 } 530 531 return size; 532 } 533 534 /* Write GNU properties. */ 535 536 static void 537 elf_write_gnu_properties (struct bfd_link_info *info, 538 bfd *abfd, bfd_byte *contents, 539 elf_property_list *list, unsigned int size, 540 unsigned int align_size) 541 { 542 unsigned int descsz; 543 unsigned int datasz; 544 Elf_External_Note *e_note; 545 546 e_note = (Elf_External_Note *) contents; 547 descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]); 548 descsz = (descsz + 3) & -(unsigned int) 4; 549 bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz); 550 bfd_h_put_32 (abfd, size - descsz, &e_note->descsz); 551 bfd_h_put_32 (abfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type); 552 memcpy (e_note->name, "GNU", sizeof "GNU"); 553 554 size = descsz; 555 for (; list != NULL; list = list->next) 556 { 557 /* Check if this property should be skipped. */ 558 if (list->property.pr_kind == property_remove) 559 continue; 560 /* There are 4 byte type + 4 byte datasz for each property. */ 561 if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE) 562 datasz = align_size; 563 else 564 datasz = list->property.pr_datasz; 565 bfd_h_put_32 (abfd, list->property.pr_type, contents + size); 566 bfd_h_put_32 (abfd, datasz, contents + size + 4); 567 size += 4 + 4; 568 569 /* Write out property value. */ 570 switch (list->property.pr_kind) 571 { 572 case property_number: 573 switch (datasz) 574 { 575 default: 576 /* Never should happen. */ 577 abort (); 578 579 case 0: 580 break; 581 582 case 4: 583 /* Save the pointer to GNU_PROPERTY_1_NEEDED so that it 584 can be updated later if needed. */ 585 if (info != NULL 586 && list->property.pr_type == GNU_PROPERTY_1_NEEDED) 587 info->needed_1_p = contents + size; 588 bfd_h_put_32 (abfd, list->property.u.number, 589 contents + size); 590 break; 591 592 case 8: 593 bfd_h_put_64 (abfd, list->property.u.number, 594 contents + size); 595 break; 596 } 597 break; 598 599 default: 600 /* Never should happen. */ 601 abort (); 602 } 603 size += datasz; 604 605 /* Align each property. */ 606 size = (size + (align_size - 1)) & ~ (align_size - 1); 607 } 608 } 609 610 /* Set up GNU properties. Return the first relocatable ELF input with 611 GNU properties if found. Otherwise, return NULL. */ 612 613 bfd * 614 _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) 615 { 616 bfd *abfd, *first_pbfd = NULL, *elf_bfd = NULL; 617 elf_property_list *list; 618 asection *sec; 619 bool has_properties = false; 620 const struct elf_backend_data *bed 621 = get_elf_backend_data (info->output_bfd); 622 unsigned int elfclass = bed->s->elfclass; 623 int elf_machine_code = bed->elf_machine_code; 624 elf_property *p; 625 626 /* Find the first relocatable ELF input with GNU properties. */ 627 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) 628 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour 629 && (abfd->flags & DYNAMIC) == 0 630 && (elf_machine_code 631 == get_elf_backend_data (abfd)->elf_machine_code) 632 && (elfclass == get_elf_backend_data (abfd)->s->elfclass)) 633 { 634 /* Ignore GNU properties from ELF objects with different machine 635 code or class. Also skip objects without a GNU_PROPERTY note 636 section. */ 637 elf_bfd = abfd; 638 639 if (elf_properties (abfd) != NULL) 640 { 641 has_properties = true; 642 643 if (bfd_get_section_by_name (abfd, 644 NOTE_GNU_PROPERTY_SECTION_NAME) 645 != NULL) 646 { 647 /* Keep .note.gnu.property section in FIRST_PBFD. */ 648 first_pbfd = abfd; 649 break; 650 } 651 } 652 } 653 654 if (info->indirect_extern_access > 0 && elf_bfd != NULL) 655 { 656 /* Support -z indirect-extern-access. */ 657 if (first_pbfd == NULL) 658 { 659 sec = bfd_make_section_with_flags (elf_bfd, 660 NOTE_GNU_PROPERTY_SECTION_NAME, 661 (SEC_ALLOC 662 | SEC_LOAD 663 | SEC_IN_MEMORY 664 | SEC_READONLY 665 | SEC_HAS_CONTENTS 666 | SEC_DATA)); 667 if (sec == NULL) 668 info->callbacks->einfo (_("%F%P: failed to create GNU property section\n")); 669 670 if (!bfd_set_section_alignment (sec, 671 elfclass == ELFCLASS64 ? 3 : 2)) 672 info->callbacks->einfo (_("%F%pA: failed to align section\n"), 673 sec); 674 675 elf_section_type (sec) = SHT_NOTE; 676 first_pbfd = elf_bfd; 677 has_properties = true; 678 } 679 680 p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_1_NEEDED, 4); 681 if (p->pr_kind == property_unknown) 682 { 683 /* Create GNU_PROPERTY_1_NEEDED. */ 684 p->u.number 685 = GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; 686 p->pr_kind = property_number; 687 } 688 else 689 p->u.number 690 |= GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; 691 } 692 693 /* Do nothing if there is no .note.gnu.property section. */ 694 if (!has_properties) 695 return NULL; 696 697 /* Merge .note.gnu.property sections. */ 698 info->callbacks->minfo (_("\n")); 699 info->callbacks->minfo (_("Merging program properties\n")); 700 info->callbacks->minfo (_("\n")); 701 702 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) 703 if (abfd != first_pbfd 704 && (abfd->flags & (DYNAMIC | BFD_PLUGIN | BFD_LINKER_CREATED)) == 0) 705 { 706 elf_property_list *null_ptr = NULL; 707 elf_property_list **listp = &null_ptr; 708 709 /* Merge .note.gnu.property section in relocatable ELF input. */ 710 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) 711 { 712 list = elf_properties (abfd); 713 714 /* Ignore GNU properties from ELF objects with different 715 machine code. */ 716 if (list != NULL 717 && (elf_machine_code 718 == get_elf_backend_data (abfd)->elf_machine_code)) 719 listp = &elf_properties (abfd); 720 } 721 else 722 list = NULL; 723 724 /* Merge properties with FIRST_PBFD. FIRST_PBFD can be NULL 725 when all properties are from ELF objects with different 726 machine code or class. */ 727 if (first_pbfd != NULL) 728 elf_merge_gnu_property_list (info, first_pbfd, abfd, listp); 729 730 if (list != NULL) 731 { 732 /* Discard the .note.gnu.property section in this bfd. */ 733 sec = bfd_get_section_by_name (abfd, 734 NOTE_GNU_PROPERTY_SECTION_NAME); 735 if (sec != NULL) 736 sec->output_section = bfd_abs_section_ptr; 737 } 738 } 739 740 /* Rewrite .note.gnu.property section so that GNU properties are 741 always sorted by type even if input GNU properties aren't sorted. */ 742 if (first_pbfd != NULL) 743 { 744 bfd_size_type size; 745 bfd_byte *contents; 746 unsigned int align_size = elfclass == ELFCLASS64 ? 8 : 4; 747 748 sec = bfd_get_section_by_name (first_pbfd, 749 NOTE_GNU_PROPERTY_SECTION_NAME); 750 BFD_ASSERT (sec != NULL); 751 752 /* Update stack size in .note.gnu.property with -z stack-size=N 753 if N > 0. */ 754 if (info->stacksize > 0) 755 { 756 bfd_vma stacksize = info->stacksize; 757 758 p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE, 759 align_size); 760 if (p->pr_kind == property_unknown) 761 { 762 /* Create GNU_PROPERTY_STACK_SIZE. */ 763 p->u.number = stacksize; 764 p->pr_kind = property_number; 765 } 766 else if (stacksize > p->u.number) 767 p->u.number = stacksize; 768 } 769 else if (elf_properties (first_pbfd) == NULL) 770 { 771 /* Discard .note.gnu.property section if all properties have 772 been removed. */ 773 sec->output_section = bfd_abs_section_ptr; 774 return NULL; 775 } 776 777 /* Fix up GNU properties. */ 778 if (bed->fixup_gnu_properties) 779 bed->fixup_gnu_properties (info, &elf_properties (first_pbfd)); 780 781 if (elf_properties (first_pbfd) == NULL) 782 { 783 /* Discard .note.gnu.property section if all properties have 784 been removed. */ 785 sec->output_section = bfd_abs_section_ptr; 786 return NULL; 787 } 788 789 /* Compute the section size. */ 790 list = elf_properties (first_pbfd); 791 size = elf_get_gnu_property_section_size (list, align_size); 792 793 /* Update .note.gnu.property section now. */ 794 sec->size = size; 795 contents = (bfd_byte *) bfd_zalloc (first_pbfd, size); 796 797 if (info->indirect_extern_access <= 0) 798 { 799 /* Get GNU_PROPERTY_1_NEEDED properties. */ 800 p = elf_find_and_remove_property (&elf_properties (first_pbfd), 801 GNU_PROPERTY_1_NEEDED, false); 802 if (p != NULL) 803 { 804 if (info->indirect_extern_access < 0) 805 { 806 /* Set indirect_extern_access to 1 to indicate that 807 it is turned on by input properties. */ 808 if ((p->u.number 809 & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) 810 != 0) 811 info->indirect_extern_access = 1; 812 } 813 else 814 /* Turn off indirect external access. */ 815 p->u.number 816 &= ~GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; 817 } 818 } 819 820 elf_write_gnu_properties (info, first_pbfd, contents, list, size, 821 align_size); 822 823 /* Cache the section contents for elf_link_input_bfd. */ 824 elf_section_data (sec)->this_hdr.contents = contents; 825 826 /* If GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, protected data 827 symbol is defined in the shared object. */ 828 if (elf_has_no_copy_on_protected (first_pbfd)) 829 info->extern_protected_data = false; 830 831 if (info->indirect_extern_access > 0) 832 { 833 /* For indirect external access, don't generate copy 834 relocations. NB: Set to nocopyreloc to 2 to indicate 835 that it is implied by indirect_extern_access. */ 836 info->nocopyreloc = 2; 837 info->extern_protected_data = false; 838 } 839 } 840 841 return first_pbfd; 842 } 843 844 /* Convert GNU property size. */ 845 846 bfd_size_type 847 _bfd_elf_convert_gnu_property_size (bfd *ibfd, bfd *obfd) 848 { 849 unsigned int align_size; 850 const struct elf_backend_data *bed; 851 elf_property_list *list = elf_properties (ibfd); 852 853 bed = get_elf_backend_data (obfd); 854 align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4; 855 856 /* Get the output .note.gnu.property section size. */ 857 return elf_get_gnu_property_section_size (list, align_size); 858 } 859 860 /* Convert GNU properties. */ 861 862 bool 863 _bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec, 864 bfd *obfd, bfd_byte **ptr, 865 bfd_size_type *ptr_size) 866 { 867 unsigned int size; 868 bfd_byte *contents; 869 unsigned int align_shift; 870 const struct elf_backend_data *bed; 871 elf_property_list *list = elf_properties (ibfd); 872 873 bed = get_elf_backend_data (obfd); 874 align_shift = bed->s->elfclass == ELFCLASS64 ? 3 : 2; 875 876 /* Get the output .note.gnu.property section size. */ 877 size = bfd_section_size (isec->output_section); 878 879 /* Update the output .note.gnu.property section alignment. */ 880 bfd_set_section_alignment (isec->output_section, align_shift); 881 882 if (size > bfd_section_size (isec)) 883 { 884 contents = (bfd_byte *) bfd_malloc (size); 885 if (contents == NULL) 886 return false; 887 free (*ptr); 888 *ptr = contents; 889 } 890 else 891 contents = *ptr; 892 893 *ptr_size = size; 894 895 /* Generate the output .note.gnu.property section. */ 896 elf_write_gnu_properties (NULL, ibfd, contents, list, size, 897 1 << align_shift); 898 899 return true; 900 } 901