GNU Binutils with patches for OS216
Revision | 68e7d8090b38bc44d0171b7ce3b89161f1938cfc (tree) |
---|---|
Time | 2016-05-04 02:40:49 |
Author | H.J. Lu <hjl.tools@gmai...> |
Commiter | H.J. Lu |
Extract convert_load_reloc from x86 convert_load
* elf32-i386.c (elf_i386_convert_load): Extract the GOT load
conversion to ...
(elf_i386_convert_load_reloc): This. New function.
* elf64-x86-64.c (elf_x86_64_convert_load): Extract the GOT load
conversion to ...
(elf_x86_64_convert_load_reloc): This. New function.
@@ -1499,6 +1499,255 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, | ||
1499 | 1499 | return TRUE; |
1500 | 1500 | } |
1501 | 1501 | |
1502 | +/* With the local symbol, foo, we convert | |
1503 | + mov foo@GOT[(%reg1)], %reg2 | |
1504 | + to | |
1505 | + lea foo[@GOTOFF(%reg1)], %reg2 | |
1506 | + and convert | |
1507 | + call/jmp *foo@GOT[(%reg)] | |
1508 | + to | |
1509 | + nop call foo/jmp foo nop | |
1510 | + When PIC is false, convert | |
1511 | + test %reg1, foo@GOT[(%reg2)] | |
1512 | + to | |
1513 | + test $foo, %reg1 | |
1514 | + and convert | |
1515 | + binop foo@GOT[(%reg1)], %reg2 | |
1516 | + to | |
1517 | + binop $foo, %reg2 | |
1518 | + where binop is one of adc, add, and, cmp, or, sbb, sub, xor | |
1519 | + instructions. */ | |
1520 | + | |
1521 | +static | |
1522 | +bfd_boolean | |
1523 | +elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, | |
1524 | + bfd_byte *contents, | |
1525 | + Elf_Internal_Rela *irel, | |
1526 | + struct elf_link_hash_entry *h, | |
1527 | + bfd_boolean *converted, | |
1528 | + struct bfd_link_info *link_info) | |
1529 | +{ | |
1530 | + struct elf_i386_link_hash_table *htab; | |
1531 | + unsigned int opcode; | |
1532 | + unsigned int modrm; | |
1533 | + bfd_boolean baseless; | |
1534 | + Elf_Internal_Sym *isym; | |
1535 | + unsigned int addend; | |
1536 | + unsigned int nop; | |
1537 | + bfd_vma nop_offset; | |
1538 | + bfd_boolean is_pic; | |
1539 | + bfd_boolean to_reloc_32; | |
1540 | + unsigned int r_type; | |
1541 | + unsigned int r_symndx; | |
1542 | + bfd_vma roff = irel->r_offset; | |
1543 | + | |
1544 | + if (roff < 2) | |
1545 | + return TRUE; | |
1546 | + | |
1547 | + /* Addend for R_386_GOT32 and R_386_GOT32X relocations must be 0. */ | |
1548 | + addend = bfd_get_32 (abfd, contents + roff); | |
1549 | + if (addend != 0) | |
1550 | + return TRUE; | |
1551 | + | |
1552 | + htab = elf_i386_hash_table (link_info); | |
1553 | + is_pic = bfd_link_pic (link_info); | |
1554 | + | |
1555 | + r_type = ELF32_R_TYPE (irel->r_info); | |
1556 | + r_symndx = ELF32_R_SYM (irel->r_info); | |
1557 | + | |
1558 | + modrm = bfd_get_8 (abfd, contents + roff - 1); | |
1559 | + baseless = (modrm & 0xc7) == 0x5; | |
1560 | + | |
1561 | + if (r_type == R_386_GOT32X && baseless && is_pic) | |
1562 | + { | |
1563 | + /* For PIC, disallow R_386_GOT32X without a base register | |
1564 | + since we don't know what the GOT base is. Allow | |
1565 | + R_386_GOT32 for existing object files. */ | |
1566 | + const char *name; | |
1567 | + | |
1568 | + if (h == NULL) | |
1569 | + { | |
1570 | + isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, | |
1571 | + r_symndx); | |
1572 | + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); | |
1573 | + } | |
1574 | + else | |
1575 | + name = h->root.root.string; | |
1576 | + | |
1577 | + (*_bfd_error_handler) | |
1578 | + (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"), | |
1579 | + abfd, name); | |
1580 | + return FALSE; | |
1581 | + } | |
1582 | + | |
1583 | + opcode = bfd_get_8 (abfd, contents + roff - 2); | |
1584 | + | |
1585 | + /* Convert mov to lea since it has been done for a while. */ | |
1586 | + if (opcode != 0x8b) | |
1587 | + { | |
1588 | + /* Only convert R_386_GOT32X relocation for call, jmp or | |
1589 | + one of adc, add, and, cmp, or, sbb, sub, test, xor | |
1590 | + instructions. */ | |
1591 | + if (r_type != R_386_GOT32X) | |
1592 | + return TRUE; | |
1593 | + } | |
1594 | + | |
1595 | + /* Convert to R_386_32 if PIC is false or there is no base | |
1596 | + register. */ | |
1597 | + to_reloc_32 = !is_pic || baseless; | |
1598 | + | |
1599 | + /* Try to convert R_386_GOT32 and R_386_GOT32X. Get the symbol | |
1600 | + referred to by the reloc. */ | |
1601 | + if (h == NULL) | |
1602 | + { | |
1603 | + if (opcode == 0x0ff) | |
1604 | + /* Convert "call/jmp *foo@GOT[(%reg)]". */ | |
1605 | + goto convert_branch; | |
1606 | + else | |
1607 | + /* Convert "mov foo@GOT[(%reg1)], %reg2", | |
1608 | + "test %reg1, foo@GOT(%reg2)" and | |
1609 | + "binop foo@GOT[(%reg1)], %reg2". */ | |
1610 | + goto convert_load; | |
1611 | + } | |
1612 | + | |
1613 | + /* Undefined weak symbol is only bound locally in executable | |
1614 | + and its reference is resolved as 0. */ | |
1615 | + if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, TRUE, | |
1616 | + elf_i386_hash_entry (h))) | |
1617 | + { | |
1618 | + if (opcode == 0xff) | |
1619 | + { | |
1620 | + /* No direct branch to 0 for PIC. */ | |
1621 | + if (is_pic) | |
1622 | + return TRUE; | |
1623 | + else | |
1624 | + goto convert_branch; | |
1625 | + } | |
1626 | + else | |
1627 | + { | |
1628 | + /* We can convert load of address 0 to R_386_32. */ | |
1629 | + to_reloc_32 = TRUE; | |
1630 | + goto convert_load; | |
1631 | + } | |
1632 | + } | |
1633 | + | |
1634 | + if (opcode == 0xff) | |
1635 | + { | |
1636 | + /* We have "call/jmp *foo@GOT[(%reg)]". */ | |
1637 | + if ((h->root.type == bfd_link_hash_defined | |
1638 | + || h->root.type == bfd_link_hash_defweak) | |
1639 | + && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
1640 | + { | |
1641 | + /* The function is locally defined. */ | |
1642 | +convert_branch: | |
1643 | + /* Convert R_386_GOT32X to R_386_PC32. */ | |
1644 | + if (modrm == 0x15 || (modrm & 0xf8) == 0x90) | |
1645 | + { | |
1646 | + /* Convert to "nop call foo". ADDR_PREFIX_OPCODE | |
1647 | + is a nop prefix. */ | |
1648 | + modrm = 0xe8; | |
1649 | + nop = link_info->call_nop_byte; | |
1650 | + if (link_info->call_nop_as_suffix) | |
1651 | + { | |
1652 | + nop_offset = roff + 3; | |
1653 | + irel->r_offset -= 1; | |
1654 | + } | |
1655 | + else | |
1656 | + nop_offset = roff - 2; | |
1657 | + } | |
1658 | + else | |
1659 | + { | |
1660 | + /* Convert to "jmp foo nop". */ | |
1661 | + modrm = 0xe9; | |
1662 | + nop = NOP_OPCODE; | |
1663 | + nop_offset = roff + 3; | |
1664 | + irel->r_offset -= 1; | |
1665 | + } | |
1666 | + | |
1667 | + bfd_put_8 (abfd, nop, contents + nop_offset); | |
1668 | + bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1); | |
1669 | + /* When converting to PC-relative relocation, we | |
1670 | + need to adjust addend by -4. */ | |
1671 | + bfd_put_32 (abfd, -4, contents + irel->r_offset); | |
1672 | + irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32); | |
1673 | + | |
1674 | + *converted = TRUE; | |
1675 | + } | |
1676 | + } | |
1677 | + else | |
1678 | + { | |
1679 | + /* We have "mov foo@GOT[(%re1g)], %reg2", | |
1680 | + "test %reg1, foo@GOT(%reg2)" and | |
1681 | + "binop foo@GOT[(%reg1)], %reg2". | |
1682 | + | |
1683 | + Avoid optimizing _DYNAMIC since ld.so may use its | |
1684 | + link-time address. */ | |
1685 | + if (h == htab->elf.hdynamic) | |
1686 | + return TRUE; | |
1687 | + | |
1688 | + /* def_regular is set by an assignment in a linker script in | |
1689 | + bfd_elf_record_link_assignment. */ | |
1690 | + if ((h->def_regular | |
1691 | + || h->root.type == bfd_link_hash_defined | |
1692 | + || h->root.type == bfd_link_hash_defweak) | |
1693 | + && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
1694 | + { | |
1695 | +convert_load: | |
1696 | + if (opcode == 0x8b) | |
1697 | + { | |
1698 | + if (to_reloc_32) | |
1699 | + { | |
1700 | + /* Convert "mov foo@GOT[(%reg1)], %reg2" to | |
1701 | + "mov $foo, %reg2" with R_386_32. */ | |
1702 | + r_type = R_386_32; | |
1703 | + modrm = 0xc0 | (modrm & 0x38) >> 3; | |
1704 | + bfd_put_8 (abfd, modrm, contents + roff - 1); | |
1705 | + opcode = 0xc7; | |
1706 | + } | |
1707 | + else | |
1708 | + { | |
1709 | + /* Convert "mov foo@GOT(%reg1), %reg2" to | |
1710 | + "lea foo@GOTOFF(%reg1), %reg2". */ | |
1711 | + r_type = R_386_GOTOFF; | |
1712 | + opcode = 0x8d; | |
1713 | + } | |
1714 | + } | |
1715 | + else | |
1716 | + { | |
1717 | + /* Only R_386_32 is supported. */ | |
1718 | + if (!to_reloc_32) | |
1719 | + return TRUE; | |
1720 | + | |
1721 | + if (opcode == 0x85) | |
1722 | + { | |
1723 | + /* Convert "test %reg1, foo@GOT(%reg2)" to | |
1724 | + "test $foo, %reg1". */ | |
1725 | + modrm = 0xc0 | (modrm & 0x38) >> 3; | |
1726 | + opcode = 0xf7; | |
1727 | + } | |
1728 | + else | |
1729 | + { | |
1730 | + /* Convert "binop foo@GOT(%reg1), %reg2" to | |
1731 | + "binop $foo, %reg2". */ | |
1732 | + modrm = (0xc0 | |
1733 | + | (modrm & 0x38) >> 3 | |
1734 | + | (opcode & 0x3c)); | |
1735 | + opcode = 0x81; | |
1736 | + } | |
1737 | + bfd_put_8 (abfd, modrm, contents + roff - 1); | |
1738 | + r_type = R_386_32; | |
1739 | + } | |
1740 | + | |
1741 | + bfd_put_8 (abfd, opcode, contents + roff - 2); | |
1742 | + irel->r_info = ELF32_R_INFO (r_symndx, r_type); | |
1743 | + | |
1744 | + *converted = TRUE; | |
1745 | + } | |
1746 | + } | |
1747 | + | |
1748 | + return TRUE; | |
1749 | +} | |
1750 | + | |
1502 | 1751 | /* Rename some of the generic section flags to better document how they |
1503 | 1752 | are used here. */ |
1504 | 1753 | #define need_convert_load sec_flg0 |
@@ -2718,37 +2967,18 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
2718 | 2967 | return TRUE; |
2719 | 2968 | } |
2720 | 2969 | |
2721 | -/* With the local symbol, foo, we convert | |
2722 | - mov foo@GOT[(%reg1)], %reg2 | |
2723 | - to | |
2724 | - lea foo[@GOTOFF(%reg1)], %reg2 | |
2725 | - and convert | |
2726 | - call/jmp *foo@GOT[(%reg)] | |
2727 | - to | |
2728 | - nop call foo/jmp foo nop | |
2729 | - When PIC is false, convert | |
2730 | - test %reg1, foo@GOT[(%reg2)] | |
2731 | - to | |
2732 | - test $foo, %reg1 | |
2733 | - and convert | |
2734 | - binop foo@GOT[(%reg1)], %reg2 | |
2735 | - to | |
2736 | - binop $foo, %reg2 | |
2737 | - where binop is one of adc, add, and, cmp, or, sbb, sub, xor | |
2738 | - instructions. */ | |
2970 | +/* Convert load via the GOT slot to load immediate. */ | |
2739 | 2971 | |
2740 | 2972 | static bfd_boolean |
2741 | 2973 | elf_i386_convert_load (bfd *abfd, asection *sec, |
2742 | 2974 | struct bfd_link_info *link_info) |
2743 | 2975 | { |
2976 | + struct elf_i386_link_hash_table *htab; | |
2744 | 2977 | Elf_Internal_Shdr *symtab_hdr; |
2745 | 2978 | Elf_Internal_Rela *internal_relocs; |
2746 | 2979 | Elf_Internal_Rela *irel, *irelend; |
2747 | 2980 | bfd_byte *contents; |
2748 | - struct elf_i386_link_hash_table *htab; | |
2749 | - bfd_boolean changed_contents; | |
2750 | - bfd_boolean changed_relocs; | |
2751 | - bfd_boolean is_pic; | |
2981 | + bfd_boolean changed; | |
2752 | 2982 | bfd_signed_vma *local_got_refcounts; |
2753 | 2983 | |
2754 | 2984 | /* Don't even try to convert non-ELF outputs. */ |
@@ -2770,13 +3000,10 @@ elf_i386_convert_load (bfd *abfd, asection *sec, | ||
2770 | 3000 | if (internal_relocs == NULL) |
2771 | 3001 | return FALSE; |
2772 | 3002 | |
3003 | + changed = FALSE; | |
2773 | 3004 | htab = elf_i386_hash_table (link_info); |
2774 | - changed_contents = FALSE; | |
2775 | - changed_relocs = FALSE; | |
2776 | 3005 | local_got_refcounts = elf_local_got_refcounts (abfd); |
2777 | 3006 | |
2778 | - is_pic = bfd_link_pic (link_info); | |
2779 | - | |
2780 | 3007 | /* Get the section contents. */ |
2781 | 3008 | if (elf_section_data (sec)->this_hdr.contents != NULL) |
2782 | 3009 | contents = elf_section_data (sec)->this_hdr.contents; |
@@ -2790,269 +3017,48 @@ elf_i386_convert_load (bfd *abfd, asection *sec, | ||
2790 | 3017 | for (irel = internal_relocs; irel < irelend; irel++) |
2791 | 3018 | { |
2792 | 3019 | unsigned int r_type = ELF32_R_TYPE (irel->r_info); |
2793 | - unsigned int r_symndx = ELF32_R_SYM (irel->r_info); | |
2794 | - unsigned int indx; | |
3020 | + unsigned int r_symndx; | |
2795 | 3021 | struct elf_link_hash_entry *h; |
2796 | - unsigned int opcode; | |
2797 | - unsigned int modrm; | |
2798 | - bfd_vma roff; | |
2799 | - bfd_boolean baseless; | |
2800 | - Elf_Internal_Sym *isym; | |
2801 | - unsigned int addend; | |
2802 | - unsigned int nop; | |
2803 | - bfd_vma nop_offset; | |
2804 | - bfd_boolean to_reloc_32; | |
3022 | + bfd_boolean converted; | |
2805 | 3023 | |
2806 | 3024 | if (r_type != R_386_GOT32 && r_type != R_386_GOT32X) |
2807 | 3025 | continue; |
2808 | 3026 | |
2809 | - roff = irel->r_offset; | |
2810 | - if (roff < 2) | |
2811 | - continue; | |
2812 | - | |
2813 | - /* Addend for R_386_GOT32 and R_386_GOT32X relocations must be 0. */ | |
2814 | - addend = bfd_get_32 (abfd, contents + roff); | |
2815 | - if (addend != 0) | |
2816 | - continue; | |
2817 | - | |
2818 | - modrm = bfd_get_8 (abfd, contents + roff - 1); | |
2819 | - baseless = (modrm & 0xc7) == 0x5; | |
2820 | - | |
2821 | - if (r_type == R_386_GOT32X && baseless && is_pic) | |
2822 | - { | |
2823 | - /* For PIC, disallow R_386_GOT32X without a base register | |
2824 | - since we don't know what the GOT base is. Allow | |
2825 | - R_386_GOT32 for existing object files. */ | |
2826 | - const char *name; | |
2827 | - | |
2828 | - if (r_symndx < symtab_hdr->sh_info) | |
2829 | - { | |
2830 | - isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, | |
2831 | - r_symndx); | |
2832 | - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); | |
2833 | - } | |
2834 | - else | |
2835 | - { | |
2836 | - indx = r_symndx - symtab_hdr->sh_info; | |
2837 | - h = elf_sym_hashes (abfd)[indx]; | |
2838 | - BFD_ASSERT (h != NULL); | |
2839 | - name = h->root.root.string; | |
2840 | - } | |
2841 | - | |
2842 | - (*_bfd_error_handler) | |
2843 | - (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"), | |
2844 | - abfd, name); | |
2845 | - goto error_return; | |
2846 | - } | |
2847 | - | |
2848 | - opcode = bfd_get_8 (abfd, contents + roff - 2); | |
2849 | - | |
2850 | - /* Convert mov to lea since it has been done for a while. */ | |
2851 | - if (opcode != 0x8b) | |
2852 | - { | |
2853 | - /* Only convert R_386_GOT32X relocation for call, jmp or | |
2854 | - one of adc, add, and, cmp, or, sbb, sub, test, xor | |
2855 | - instructions. */ | |
2856 | - if (r_type != R_386_GOT32X) | |
2857 | - continue; | |
2858 | - } | |
2859 | - | |
2860 | - /* Convert to R_386_32 if PIC is false or there is no base | |
2861 | - register. */ | |
2862 | - to_reloc_32 = !is_pic || baseless; | |
2863 | - | |
2864 | - /* Try to convert R_386_GOT32 and R_386_GOT32X. Get the symbol | |
2865 | - referred to by the reloc. */ | |
3027 | + r_symndx = ELF32_R_SYM (irel->r_info); | |
2866 | 3028 | if (r_symndx < symtab_hdr->sh_info) |
3029 | + h = elf_i386_get_local_sym_hash (htab, sec->owner, | |
3030 | + (const Elf_Internal_Rela *) irel, | |
3031 | + FALSE); | |
3032 | + else | |
2867 | 3033 | { |
2868 | - isym = bfd_sym_from_r_symndx (&htab->sym_cache, | |
2869 | - abfd, r_symndx); | |
2870 | - | |
2871 | - /* STT_GNU_IFUNC must keep GOT32 relocations. */ | |
2872 | - if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) | |
2873 | - continue; | |
2874 | - | |
2875 | - h = NULL; | |
2876 | - if (opcode == 0x0ff) | |
2877 | - /* Convert "call/jmp *foo@GOT[(%reg)]". */ | |
2878 | - goto convert_branch; | |
2879 | - else | |
2880 | - /* Convert "mov foo@GOT[(%reg1)], %reg2", | |
2881 | - "test %reg1, foo@GOT(%reg2)" and | |
2882 | - "binop foo@GOT[(%reg1)], %reg2". */ | |
2883 | - goto convert_load; | |
3034 | + h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info]; | |
3035 | + while (h->root.type == bfd_link_hash_indirect | |
3036 | + || h->root.type == bfd_link_hash_warning) | |
3037 | + h = (struct elf_link_hash_entry *) h->root.u.i.link; | |
2884 | 3038 | } |
2885 | 3039 | |
2886 | - indx = r_symndx - symtab_hdr->sh_info; | |
2887 | - h = elf_sym_hashes (abfd)[indx]; | |
2888 | - BFD_ASSERT (h != NULL); | |
2889 | - | |
2890 | - while (h->root.type == bfd_link_hash_indirect | |
2891 | - || h->root.type == bfd_link_hash_warning) | |
2892 | - h = (struct elf_link_hash_entry *) h->root.u.i.link; | |
2893 | - | |
2894 | 3040 | /* STT_GNU_IFUNC must keep GOT32 relocations. */ |
2895 | - if (h->type == STT_GNU_IFUNC) | |
3041 | + if (h != NULL && h->type == STT_GNU_IFUNC) | |
2896 | 3042 | continue; |
2897 | 3043 | |
2898 | - /* Undefined weak symbol is only bound locally in executable | |
2899 | - and its reference is resolved as 0. */ | |
2900 | - if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, TRUE, | |
2901 | - elf_i386_hash_entry (h))) | |
2902 | - { | |
2903 | - if (opcode == 0xff) | |
2904 | - { | |
2905 | - /* No direct branch to 0 for PIC. */ | |
2906 | - if (is_pic) | |
2907 | - continue; | |
2908 | - else | |
2909 | - goto convert_branch; | |
2910 | - } | |
2911 | - else | |
2912 | - { | |
2913 | - /* We can convert load of address 0 to R_386_32. */ | |
2914 | - to_reloc_32 = TRUE; | |
2915 | - goto convert_load; | |
2916 | - } | |
2917 | - } | |
3044 | + converted = FALSE; | |
3045 | + if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents, | |
3046 | + irel, h, &converted, link_info)) | |
3047 | + goto error_return; | |
2918 | 3048 | |
2919 | - if (opcode == 0xff) | |
3049 | + if (converted) | |
2920 | 3050 | { |
2921 | - /* We have "call/jmp *foo@GOT[(%reg)]". */ | |
2922 | - if ((h->root.type == bfd_link_hash_defined | |
2923 | - || h->root.type == bfd_link_hash_defweak) | |
2924 | - && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
3051 | + changed = converted; | |
3052 | + if (h) | |
2925 | 3053 | { |
2926 | - /* The function is locally defined. */ | |
2927 | -convert_branch: | |
2928 | - /* Convert R_386_GOT32X to R_386_PC32. */ | |
2929 | - if (modrm == 0x15 || (modrm & 0xf8) == 0x90) | |
2930 | - { | |
2931 | - /* Convert to "nop call foo". ADDR_PREFIX_OPCODE | |
2932 | - is a nop prefix. */ | |
2933 | - modrm = 0xe8; | |
2934 | - nop = link_info->call_nop_byte; | |
2935 | - if (link_info->call_nop_as_suffix) | |
2936 | - { | |
2937 | - nop_offset = roff + 3; | |
2938 | - irel->r_offset -= 1; | |
2939 | - } | |
2940 | - else | |
2941 | - nop_offset = roff - 2; | |
2942 | - } | |
2943 | - else | |
2944 | - { | |
2945 | - /* Convert to "jmp foo nop". */ | |
2946 | - modrm = 0xe9; | |
2947 | - nop = NOP_OPCODE; | |
2948 | - nop_offset = roff + 3; | |
2949 | - irel->r_offset -= 1; | |
2950 | - } | |
2951 | - | |
2952 | - bfd_put_8 (abfd, nop, contents + nop_offset); | |
2953 | - bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1); | |
2954 | - /* When converting to PC-relative relocation, we | |
2955 | - need to adjust addend by -4. */ | |
2956 | - bfd_put_32 (abfd, -4, contents + irel->r_offset); | |
2957 | - irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32); | |
2958 | - | |
2959 | - if (h) | |
2960 | - { | |
2961 | - if (h->got.refcount > 0) | |
2962 | - h->got.refcount -= 1; | |
2963 | - } | |
2964 | - else | |
2965 | - { | |
2966 | - if (local_got_refcounts != NULL | |
2967 | - && local_got_refcounts[r_symndx] > 0) | |
2968 | - local_got_refcounts[r_symndx] -= 1; | |
2969 | - } | |
2970 | - | |
2971 | - changed_contents = TRUE; | |
2972 | - changed_relocs = TRUE; | |
3054 | + if (h->got.refcount > 0) | |
3055 | + h->got.refcount -= 1; | |
2973 | 3056 | } |
2974 | - } | |
2975 | - else | |
2976 | - { | |
2977 | - /* We have "mov foo@GOT[(%re1g)], %reg2", | |
2978 | - "test %reg1, foo@GOT(%reg2)" and | |
2979 | - "binop foo@GOT[(%reg1)], %reg2". | |
2980 | - | |
2981 | - Avoid optimizing _DYNAMIC since ld.so may use its | |
2982 | - link-time address. */ | |
2983 | - if (h == htab->elf.hdynamic) | |
2984 | - continue; | |
2985 | - | |
2986 | - /* def_regular is set by an assignment in a linker script in | |
2987 | - bfd_elf_record_link_assignment. */ | |
2988 | - if ((h->def_regular | |
2989 | - || h->root.type == bfd_link_hash_defined | |
2990 | - || h->root.type == bfd_link_hash_defweak) | |
2991 | - && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
3057 | + else | |
2992 | 3058 | { |
2993 | -convert_load: | |
2994 | - if (opcode == 0x8b) | |
2995 | - { | |
2996 | - if (to_reloc_32) | |
2997 | - { | |
2998 | - /* Convert "mov foo@GOT[(%reg1)], %reg2" to | |
2999 | - "mov $foo, %reg2" with R_386_32. */ | |
3000 | - r_type = R_386_32; | |
3001 | - modrm = 0xc0 | (modrm & 0x38) >> 3; | |
3002 | - bfd_put_8 (abfd, modrm, contents + roff - 1); | |
3003 | - opcode = 0xc7; | |
3004 | - } | |
3005 | - else | |
3006 | - { | |
3007 | - /* Convert "mov foo@GOT(%reg1), %reg2" to | |
3008 | - "lea foo@GOTOFF(%reg1), %reg2". */ | |
3009 | - r_type = R_386_GOTOFF; | |
3010 | - opcode = 0x8d; | |
3011 | - } | |
3012 | - } | |
3013 | - else | |
3014 | - { | |
3015 | - /* Only R_386_32 is supported. */ | |
3016 | - if (!to_reloc_32) | |
3017 | - continue; | |
3018 | - | |
3019 | - if (opcode == 0x85) | |
3020 | - { | |
3021 | - /* Convert "test %reg1, foo@GOT(%reg2)" to | |
3022 | - "test $foo, %reg1". */ | |
3023 | - modrm = 0xc0 | (modrm & 0x38) >> 3; | |
3024 | - opcode = 0xf7; | |
3025 | - } | |
3026 | - else | |
3027 | - { | |
3028 | - /* Convert "binop foo@GOT(%reg1), %reg2" to | |
3029 | - "binop $foo, %reg2". */ | |
3030 | - modrm = (0xc0 | |
3031 | - | (modrm & 0x38) >> 3 | |
3032 | - | (opcode & 0x3c)); | |
3033 | - opcode = 0x81; | |
3034 | - } | |
3035 | - bfd_put_8 (abfd, modrm, contents + roff - 1); | |
3036 | - r_type = R_386_32; | |
3037 | - } | |
3038 | - | |
3039 | - bfd_put_8 (abfd, opcode, contents + roff - 2); | |
3040 | - irel->r_info = ELF32_R_INFO (r_symndx, r_type); | |
3041 | - | |
3042 | - if (h) | |
3043 | - { | |
3044 | - if (h->got.refcount > 0) | |
3045 | - h->got.refcount -= 1; | |
3046 | - } | |
3047 | - else | |
3048 | - { | |
3049 | - if (local_got_refcounts != NULL | |
3050 | - && local_got_refcounts[r_symndx] > 0) | |
3051 | - local_got_refcounts[r_symndx] -= 1; | |
3052 | - } | |
3053 | - | |
3054 | - changed_contents = TRUE; | |
3055 | - changed_relocs = TRUE; | |
3059 | + if (local_got_refcounts != NULL | |
3060 | + && local_got_refcounts[r_symndx] > 0) | |
3061 | + local_got_refcounts[r_symndx] -= 1; | |
3056 | 3062 | } |
3057 | 3063 | } |
3058 | 3064 | } |
@@ -3060,7 +3066,7 @@ convert_load: | ||
3060 | 3066 | if (contents != NULL |
3061 | 3067 | && elf_section_data (sec)->this_hdr.contents != contents) |
3062 | 3068 | { |
3063 | - if (!changed_contents && !link_info->keep_memory) | |
3069 | + if (!changed && !link_info->keep_memory) | |
3064 | 3070 | free (contents); |
3065 | 3071 | else |
3066 | 3072 | { |
@@ -3071,7 +3077,7 @@ convert_load: | ||
3071 | 3077 | |
3072 | 3078 | if (elf_section_data (sec)->relocs != internal_relocs) |
3073 | 3079 | { |
3074 | - if (!changed_relocs) | |
3080 | + if (!changed) | |
3075 | 3081 | free (internal_relocs); |
3076 | 3082 | else |
3077 | 3083 | elf_section_data (sec)->relocs = internal_relocs; |
@@ -1634,6 +1634,401 @@ elf_x86_64_need_pic (bfd *input_bfd, asection *sec, | ||
1634 | 1634 | return FALSE; |
1635 | 1635 | } |
1636 | 1636 | |
1637 | +/* With the local symbol, foo, we convert | |
1638 | + mov foo@GOTPCREL(%rip), %reg | |
1639 | + to | |
1640 | + lea foo(%rip), %reg | |
1641 | + and convert | |
1642 | + call/jmp *foo@GOTPCREL(%rip) | |
1643 | + to | |
1644 | + nop call foo/jmp foo nop | |
1645 | + When PIC is false, convert | |
1646 | + test %reg, foo@GOTPCREL(%rip) | |
1647 | + to | |
1648 | + test $foo, %reg | |
1649 | + and convert | |
1650 | + binop foo@GOTPCREL(%rip), %reg | |
1651 | + to | |
1652 | + binop $foo, %reg | |
1653 | + where binop is one of adc, add, and, cmp, or, sbb, sub, xor | |
1654 | + instructions. */ | |
1655 | + | |
1656 | +static bfd_boolean | |
1657 | +elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec, | |
1658 | + bfd_byte *contents, | |
1659 | + Elf_Internal_Rela *irel, | |
1660 | + struct elf_link_hash_entry *h, | |
1661 | + bfd_boolean *converted, | |
1662 | + struct bfd_link_info *link_info) | |
1663 | +{ | |
1664 | + struct elf_x86_64_link_hash_table *htab; | |
1665 | + bfd_boolean is_pic; | |
1666 | + bfd_boolean require_reloc_pc32; | |
1667 | + bfd_boolean relocx; | |
1668 | + bfd_boolean to_reloc_pc32; | |
1669 | + asection *tsec; | |
1670 | + char symtype; | |
1671 | + bfd_signed_vma raddend; | |
1672 | + unsigned int opcode; | |
1673 | + unsigned int modrm; | |
1674 | + unsigned int r_type = ELF32_R_TYPE (irel->r_info); | |
1675 | + unsigned int r_symndx; | |
1676 | + bfd_vma toff; | |
1677 | + bfd_vma roff = irel->r_offset; | |
1678 | + | |
1679 | + if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) | |
1680 | + return TRUE; | |
1681 | + | |
1682 | + raddend = irel->r_addend; | |
1683 | + /* Addend for 32-bit PC-relative relocation must be -4. */ | |
1684 | + if (raddend != -4) | |
1685 | + return TRUE; | |
1686 | + | |
1687 | + htab = elf_x86_64_hash_table (link_info); | |
1688 | + is_pic = bfd_link_pic (link_info); | |
1689 | + | |
1690 | + relocx = (r_type == R_X86_64_GOTPCRELX | |
1691 | + || r_type == R_X86_64_REX_GOTPCRELX); | |
1692 | + | |
1693 | + /* TRUE if we can convert only to R_X86_64_PC32. Enable it for | |
1694 | + --no-relax. */ | |
1695 | + require_reloc_pc32 | |
1696 | + = link_info->disable_target_specific_optimizations > 1; | |
1697 | + | |
1698 | + r_symndx = htab->r_sym (irel->r_info); | |
1699 | + | |
1700 | + opcode = bfd_get_8 (abfd, contents + roff - 2); | |
1701 | + | |
1702 | + /* Convert mov to lea since it has been done for a while. */ | |
1703 | + if (opcode != 0x8b) | |
1704 | + { | |
1705 | + /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX | |
1706 | + for call, jmp or one of adc, add, and, cmp, or, sbb, sub, | |
1707 | + test, xor instructions. */ | |
1708 | + if (!relocx) | |
1709 | + return TRUE; | |
1710 | + } | |
1711 | + | |
1712 | + /* We convert only to R_X86_64_PC32: | |
1713 | + 1. Branch. | |
1714 | + 2. R_X86_64_GOTPCREL since we can't modify REX byte. | |
1715 | + 3. require_reloc_pc32 is true. | |
1716 | + 4. PIC. | |
1717 | + */ | |
1718 | + to_reloc_pc32 = (opcode == 0xff | |
1719 | + || !relocx | |
1720 | + || require_reloc_pc32 | |
1721 | + || is_pic); | |
1722 | + | |
1723 | + /* Get the symbol referred to by the reloc. */ | |
1724 | + if (h == NULL) | |
1725 | + { | |
1726 | + Elf_Internal_Sym *isym | |
1727 | + = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); | |
1728 | + | |
1729 | + /* Skip relocation against undefined symbols. */ | |
1730 | + if (isym->st_shndx == SHN_UNDEF) | |
1731 | + return TRUE; | |
1732 | + | |
1733 | + symtype = ELF_ST_TYPE (isym->st_info); | |
1734 | + | |
1735 | + if (isym->st_shndx == SHN_ABS) | |
1736 | + tsec = bfd_abs_section_ptr; | |
1737 | + else if (isym->st_shndx == SHN_COMMON) | |
1738 | + tsec = bfd_com_section_ptr; | |
1739 | + else if (isym->st_shndx == SHN_X86_64_LCOMMON) | |
1740 | + tsec = &_bfd_elf_large_com_section; | |
1741 | + else | |
1742 | + tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); | |
1743 | + | |
1744 | + toff = isym->st_value; | |
1745 | + } | |
1746 | + else | |
1747 | + { | |
1748 | + /* Undefined weak symbol is only bound locally in executable | |
1749 | + and its reference is resolved as 0 without relocation | |
1750 | + overflow. We can only perform this optimization for | |
1751 | + GOTPCRELX relocations since we need to modify REX byte. | |
1752 | + It is OK convert mov with R_X86_64_GOTPCREL to | |
1753 | + R_X86_64_PC32. */ | |
1754 | + if ((relocx || opcode == 0x8b) | |
1755 | + && UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, | |
1756 | + TRUE, | |
1757 | + elf_x86_64_hash_entry (h))) | |
1758 | + { | |
1759 | + if (opcode == 0xff) | |
1760 | + { | |
1761 | + /* Skip for branch instructions since R_X86_64_PC32 | |
1762 | + may overflow. */ | |
1763 | + if (require_reloc_pc32) | |
1764 | + return TRUE; | |
1765 | + } | |
1766 | + else if (relocx) | |
1767 | + { | |
1768 | + /* For non-branch instructions, we can convert to | |
1769 | + R_X86_64_32/R_X86_64_32S since we know if there | |
1770 | + is a REX byte. */ | |
1771 | + to_reloc_pc32 = FALSE; | |
1772 | + } | |
1773 | + | |
1774 | + /* Since we don't know the current PC when PIC is true, | |
1775 | + we can't convert to R_X86_64_PC32. */ | |
1776 | + if (to_reloc_pc32 && is_pic) | |
1777 | + return TRUE; | |
1778 | + | |
1779 | + goto convert; | |
1780 | + } | |
1781 | + /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since | |
1782 | + ld.so may use its link-time address. */ | |
1783 | + else if ((h->def_regular | |
1784 | + || h->root.type == bfd_link_hash_defined | |
1785 | + || h->root.type == bfd_link_hash_defweak) | |
1786 | + && h != htab->elf.hdynamic | |
1787 | + && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
1788 | + { | |
1789 | + /* bfd_link_hash_new or bfd_link_hash_undefined is | |
1790 | + set by an assignment in a linker script in | |
1791 | + bfd_elf_record_link_assignment. */ | |
1792 | + if (h->def_regular | |
1793 | + && (h->root.type == bfd_link_hash_new | |
1794 | + || h->root.type == bfd_link_hash_undefined)) | |
1795 | + { | |
1796 | + /* Skip since R_X86_64_32/R_X86_64_32S may overflow. */ | |
1797 | + if (require_reloc_pc32) | |
1798 | + return TRUE; | |
1799 | + goto convert; | |
1800 | + } | |
1801 | + tsec = h->root.u.def.section; | |
1802 | + toff = h->root.u.def.value; | |
1803 | + symtype = h->type; | |
1804 | + } | |
1805 | + else | |
1806 | + return TRUE; | |
1807 | + } | |
1808 | + | |
1809 | + /* We can only estimate relocation overflow for R_X86_64_PC32. */ | |
1810 | + if (!to_reloc_pc32) | |
1811 | + goto convert; | |
1812 | + | |
1813 | + if (tsec->sec_info_type == SEC_INFO_TYPE_MERGE) | |
1814 | + { | |
1815 | + /* At this stage in linking, no SEC_MERGE symbol has been | |
1816 | + adjusted, so all references to such symbols need to be | |
1817 | + passed through _bfd_merged_section_offset. (Later, in | |
1818 | + relocate_section, all SEC_MERGE symbols *except* for | |
1819 | + section symbols have been adjusted.) | |
1820 | + | |
1821 | + gas may reduce relocations against symbols in SEC_MERGE | |
1822 | + sections to a relocation against the section symbol when | |
1823 | + the original addend was zero. When the reloc is against | |
1824 | + a section symbol we should include the addend in the | |
1825 | + offset passed to _bfd_merged_section_offset, since the | |
1826 | + location of interest is the original symbol. On the | |
1827 | + other hand, an access to "sym+addend" where "sym" is not | |
1828 | + a section symbol should not include the addend; Such an | |
1829 | + access is presumed to be an offset from "sym"; The | |
1830 | + location of interest is just "sym". */ | |
1831 | + if (symtype == STT_SECTION) | |
1832 | + toff += raddend; | |
1833 | + | |
1834 | + toff = _bfd_merged_section_offset (abfd, &tsec, | |
1835 | + elf_section_data (tsec)->sec_info, | |
1836 | + toff); | |
1837 | + | |
1838 | + if (symtype != STT_SECTION) | |
1839 | + toff += raddend; | |
1840 | + } | |
1841 | + else | |
1842 | + toff += raddend; | |
1843 | + | |
1844 | + /* Don't convert if R_X86_64_PC32 relocation overflows. */ | |
1845 | + if (tsec->output_section == sec->output_section) | |
1846 | + { | |
1847 | + if ((toff - roff + 0x80000000) > 0xffffffff) | |
1848 | + return TRUE; | |
1849 | + } | |
1850 | + else | |
1851 | + { | |
1852 | + bfd_signed_vma distance; | |
1853 | + | |
1854 | + /* At this point, we don't know the load addresses of TSEC | |
1855 | + section nor SEC section. We estimate the distrance between | |
1856 | + SEC and TSEC. We store the estimated distances in the | |
1857 | + compressed_size field of the output section, which is only | |
1858 | + used to decompress the compressed input section. */ | |
1859 | + if (sec->output_section->compressed_size == 0) | |
1860 | + { | |
1861 | + asection *asect; | |
1862 | + bfd_size_type size = 0; | |
1863 | + for (asect = link_info->output_bfd->sections; | |
1864 | + asect != NULL; | |
1865 | + asect = asect->next) | |
1866 | + /* Skip debug sections since compressed_size is used to | |
1867 | + compress debug sections. */ | |
1868 | + if ((asect->flags & SEC_DEBUGGING) == 0) | |
1869 | + { | |
1870 | + asection *i; | |
1871 | + for (i = asect->map_head.s; | |
1872 | + i != NULL; | |
1873 | + i = i->map_head.s) | |
1874 | + { | |
1875 | + size = align_power (size, i->alignment_power); | |
1876 | + size += i->size; | |
1877 | + } | |
1878 | + asect->compressed_size = size; | |
1879 | + } | |
1880 | + } | |
1881 | + | |
1882 | + /* Don't convert GOTPCREL relocations if TSEC isn't placed | |
1883 | + after SEC. */ | |
1884 | + distance = (tsec->output_section->compressed_size | |
1885 | + - sec->output_section->compressed_size); | |
1886 | + if (distance < 0) | |
1887 | + return TRUE; | |
1888 | + | |
1889 | + /* Take PT_GNU_RELRO segment into account by adding | |
1890 | + maxpagesize. */ | |
1891 | + if ((toff + distance + get_elf_backend_data (abfd)->maxpagesize | |
1892 | + - roff + 0x80000000) > 0xffffffff) | |
1893 | + return TRUE; | |
1894 | + } | |
1895 | + | |
1896 | +convert: | |
1897 | + if (opcode == 0xff) | |
1898 | + { | |
1899 | + /* We have "call/jmp *foo@GOTPCREL(%rip)". */ | |
1900 | + unsigned int nop; | |
1901 | + unsigned int disp; | |
1902 | + bfd_vma nop_offset; | |
1903 | + | |
1904 | + /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to | |
1905 | + R_X86_64_PC32. */ | |
1906 | + modrm = bfd_get_8 (abfd, contents + roff - 1); | |
1907 | + if (modrm == 0x25) | |
1908 | + { | |
1909 | + /* Convert to "jmp foo nop". */ | |
1910 | + modrm = 0xe9; | |
1911 | + nop = NOP_OPCODE; | |
1912 | + nop_offset = irel->r_offset + 3; | |
1913 | + disp = bfd_get_32 (abfd, contents + irel->r_offset); | |
1914 | + irel->r_offset -= 1; | |
1915 | + bfd_put_32 (abfd, disp, contents + irel->r_offset); | |
1916 | + } | |
1917 | + else | |
1918 | + { | |
1919 | + /* Convert to "nop call foo". ADDR_PREFIX_OPCODE | |
1920 | + is a nop prefix. */ | |
1921 | + modrm = 0xe8; | |
1922 | + nop = link_info->call_nop_byte; | |
1923 | + if (link_info->call_nop_as_suffix) | |
1924 | + { | |
1925 | + nop_offset = irel->r_offset + 3; | |
1926 | + disp = bfd_get_32 (abfd, contents + irel->r_offset); | |
1927 | + irel->r_offset -= 1; | |
1928 | + bfd_put_32 (abfd, disp, contents + irel->r_offset); | |
1929 | + } | |
1930 | + else | |
1931 | + nop_offset = irel->r_offset - 2; | |
1932 | + } | |
1933 | + bfd_put_8 (abfd, nop, contents + nop_offset); | |
1934 | + bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1); | |
1935 | + r_type = R_X86_64_PC32; | |
1936 | + } | |
1937 | + else | |
1938 | + { | |
1939 | + unsigned int rex; | |
1940 | + unsigned int rex_mask = REX_R; | |
1941 | + | |
1942 | + if (r_type == R_X86_64_REX_GOTPCRELX) | |
1943 | + rex = bfd_get_8 (abfd, contents + roff - 3); | |
1944 | + else | |
1945 | + rex = 0; | |
1946 | + | |
1947 | + if (opcode == 0x8b) | |
1948 | + { | |
1949 | + if (to_reloc_pc32) | |
1950 | + { | |
1951 | + /* Convert "mov foo@GOTPCREL(%rip), %reg" to | |
1952 | + "lea foo(%rip), %reg". */ | |
1953 | + opcode = 0x8d; | |
1954 | + r_type = R_X86_64_PC32; | |
1955 | + } | |
1956 | + else | |
1957 | + { | |
1958 | + /* Convert "mov foo@GOTPCREL(%rip), %reg" to | |
1959 | + "mov $foo, %reg". */ | |
1960 | + opcode = 0xc7; | |
1961 | + modrm = bfd_get_8 (abfd, contents + roff - 1); | |
1962 | + modrm = 0xc0 | (modrm & 0x38) >> 3; | |
1963 | + if ((rex & REX_W) != 0 | |
1964 | + && ABI_64_P (link_info->output_bfd)) | |
1965 | + { | |
1966 | + /* Keep the REX_W bit in REX byte for LP64. */ | |
1967 | + r_type = R_X86_64_32S; | |
1968 | + goto rewrite_modrm_rex; | |
1969 | + } | |
1970 | + else | |
1971 | + { | |
1972 | + /* If the REX_W bit in REX byte isn't needed, | |
1973 | + use R_X86_64_32 and clear the W bit to avoid | |
1974 | + sign-extend imm32 to imm64. */ | |
1975 | + r_type = R_X86_64_32; | |
1976 | + /* Clear the W bit in REX byte. */ | |
1977 | + rex_mask |= REX_W; | |
1978 | + goto rewrite_modrm_rex; | |
1979 | + } | |
1980 | + } | |
1981 | + } | |
1982 | + else | |
1983 | + { | |
1984 | + /* R_X86_64_PC32 isn't supported. */ | |
1985 | + if (to_reloc_pc32) | |
1986 | + return TRUE; | |
1987 | + | |
1988 | + modrm = bfd_get_8 (abfd, contents + roff - 1); | |
1989 | + if (opcode == 0x85) | |
1990 | + { | |
1991 | + /* Convert "test %reg, foo@GOTPCREL(%rip)" to | |
1992 | + "test $foo, %reg". */ | |
1993 | + modrm = 0xc0 | (modrm & 0x38) >> 3; | |
1994 | + opcode = 0xf7; | |
1995 | + } | |
1996 | + else | |
1997 | + { | |
1998 | + /* Convert "binop foo@GOTPCREL(%rip), %reg" to | |
1999 | + "binop $foo, %reg". */ | |
2000 | + modrm = 0xc0 | (modrm & 0x38) >> 3 | (opcode & 0x3c); | |
2001 | + opcode = 0x81; | |
2002 | + } | |
2003 | + | |
2004 | + /* Use R_X86_64_32 with 32-bit operand to avoid relocation | |
2005 | + overflow when sign-extending imm32 to imm64. */ | |
2006 | + r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32; | |
2007 | + | |
2008 | +rewrite_modrm_rex: | |
2009 | + bfd_put_8 (abfd, modrm, contents + roff - 1); | |
2010 | + | |
2011 | + if (rex) | |
2012 | + { | |
2013 | + /* Move the R bit to the B bit in REX byte. */ | |
2014 | + rex = (rex & ~rex_mask) | (rex & REX_R) >> 2; | |
2015 | + bfd_put_8 (abfd, rex, contents + roff - 3); | |
2016 | + } | |
2017 | + | |
2018 | + /* No addend for R_X86_64_32/R_X86_64_32S relocations. */ | |
2019 | + irel->r_addend = 0; | |
2020 | + } | |
2021 | + | |
2022 | + bfd_put_8 (abfd, opcode, contents + roff - 2); | |
2023 | + } | |
2024 | + | |
2025 | + irel->r_info = htab->r_info (r_symndx, r_type); | |
2026 | + | |
2027 | + *converted = TRUE; | |
2028 | + | |
2029 | + return TRUE; | |
2030 | +} | |
2031 | + | |
1637 | 2032 | /* Look through the relocs for a section during the first phase, and |
1638 | 2033 | calculate needed space in the global offset table, procedure |
1639 | 2034 | linkage table, and dynamic reloc sections. */ |
@@ -2946,24 +3341,7 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, | ||
2946 | 3341 | return TRUE; |
2947 | 3342 | } |
2948 | 3343 | |
2949 | -/* With the local symbol, foo, we convert | |
2950 | - mov foo@GOTPCREL(%rip), %reg | |
2951 | - to | |
2952 | - lea foo(%rip), %reg | |
2953 | - and convert | |
2954 | - call/jmp *foo@GOTPCREL(%rip) | |
2955 | - to | |
2956 | - nop call foo/jmp foo nop | |
2957 | - When PIC is false, convert | |
2958 | - test %reg, foo@GOTPCREL(%rip) | |
2959 | - to | |
2960 | - test $foo, %reg | |
2961 | - and convert | |
2962 | - binop foo@GOTPCREL(%rip), %reg | |
2963 | - to | |
2964 | - binop $foo, %reg | |
2965 | - where binop is one of adc, add, and, cmp, or, sbb, sub, xor | |
2966 | - instructions. */ | |
3344 | +/* Convert load via the GOT slot to load immediate. */ | |
2967 | 3345 | |
2968 | 3346 | static bfd_boolean |
2969 | 3347 | elf_x86_64_convert_load (bfd *abfd, asection *sec, |
@@ -2974,12 +3352,8 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec, | ||
2974 | 3352 | Elf_Internal_Rela *irel, *irelend; |
2975 | 3353 | bfd_byte *contents; |
2976 | 3354 | struct elf_x86_64_link_hash_table *htab; |
2977 | - bfd_boolean changed_contents; | |
2978 | - bfd_boolean changed_relocs; | |
3355 | + bfd_boolean changed; | |
2979 | 3356 | bfd_signed_vma *local_got_refcounts; |
2980 | - bfd_vma maxpagesize; | |
2981 | - bfd_boolean is_pic; | |
2982 | - bfd_boolean require_reloc_pc32; | |
2983 | 3357 | |
2984 | 3358 | /* Don't even try to convert non-ELF outputs. */ |
2985 | 3359 | if (!is_elf_hash_table (link_info->hash)) |
@@ -3000,11 +3374,9 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec, | ||
3000 | 3374 | if (internal_relocs == NULL) |
3001 | 3375 | return FALSE; |
3002 | 3376 | |
3377 | + changed = FALSE; | |
3003 | 3378 | htab = elf_x86_64_hash_table (link_info); |
3004 | - changed_contents = FALSE; | |
3005 | - changed_relocs = FALSE; | |
3006 | 3379 | local_got_refcounts = elf_local_got_refcounts (abfd); |
3007 | - maxpagesize = get_elf_backend_data (abfd)->maxpagesize; | |
3008 | 3380 | |
3009 | 3381 | /* Get the section contents. */ |
3010 | 3382 | if (elf_section_data (sec)->this_hdr.contents != NULL) |
@@ -3015,405 +3387,62 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec, | ||
3015 | 3387 | goto error_return; |
3016 | 3388 | } |
3017 | 3389 | |
3018 | - is_pic = bfd_link_pic (link_info); | |
3019 | - | |
3020 | - /* TRUE if we can convert only to R_X86_64_PC32. Enable it for | |
3021 | - --no-relax. */ | |
3022 | - require_reloc_pc32 | |
3023 | - = link_info->disable_target_specific_optimizations > 1; | |
3024 | - | |
3025 | 3390 | irelend = internal_relocs + sec->reloc_count; |
3026 | 3391 | for (irel = internal_relocs; irel < irelend; irel++) |
3027 | 3392 | { |
3028 | 3393 | unsigned int r_type = ELF32_R_TYPE (irel->r_info); |
3029 | - unsigned int r_symndx = htab->r_sym (irel->r_info); | |
3030 | - unsigned int indx; | |
3394 | + unsigned int r_symndx; | |
3031 | 3395 | struct elf_link_hash_entry *h; |
3032 | - asection *tsec; | |
3033 | - char symtype; | |
3034 | - bfd_vma toff, roff; | |
3035 | - bfd_signed_vma raddend; | |
3036 | - unsigned int opcode; | |
3037 | - unsigned int modrm; | |
3038 | - bfd_boolean relocx; | |
3039 | - bfd_boolean to_reloc_pc32; | |
3040 | - | |
3041 | - relocx = (r_type == R_X86_64_GOTPCRELX | |
3042 | - || r_type == R_X86_64_REX_GOTPCRELX); | |
3043 | - if (!relocx && r_type != R_X86_64_GOTPCREL) | |
3044 | - continue; | |
3396 | + bfd_boolean converted; | |
3045 | 3397 | |
3046 | - roff = irel->r_offset; | |
3047 | - if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) | |
3398 | + if (r_type != R_X86_64_GOTPCRELX | |
3399 | + && r_type != R_X86_64_REX_GOTPCRELX | |
3400 | + && r_type != R_X86_64_GOTPCREL) | |
3048 | 3401 | continue; |
3049 | 3402 | |
3050 | - raddend = irel->r_addend; | |
3051 | - /* Addend for 32-bit PC-relative relocation must be -4. */ | |
3052 | - if (raddend != -4) | |
3053 | - continue; | |
3054 | - | |
3055 | - opcode = bfd_get_8 (abfd, contents + roff - 2); | |
3056 | - | |
3057 | - /* Convert mov to lea since it has been done for a while. */ | |
3058 | - if (opcode != 0x8b) | |
3059 | - { | |
3060 | - /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX | |
3061 | - for call, jmp or one of adc, add, and, cmp, or, sbb, sub, | |
3062 | - test, xor instructions. */ | |
3063 | - if (!relocx) | |
3064 | - continue; | |
3065 | - } | |
3066 | - | |
3067 | - /* We convert only to R_X86_64_PC32: | |
3068 | - 1. Branch. | |
3069 | - 2. R_X86_64_GOTPCREL since we can't modify REX byte. | |
3070 | - 3. require_reloc_pc32 is true. | |
3071 | - 4. PIC. | |
3072 | - */ | |
3073 | - to_reloc_pc32 = (opcode == 0xff | |
3074 | - || !relocx | |
3075 | - || require_reloc_pc32 | |
3076 | - || is_pic); | |
3077 | - | |
3078 | - /* Get the symbol referred to by the reloc. */ | |
3403 | + r_symndx = htab->r_sym (irel->r_info); | |
3079 | 3404 | if (r_symndx < symtab_hdr->sh_info) |
3080 | - { | |
3081 | - Elf_Internal_Sym *isym; | |
3082 | - | |
3083 | - isym = bfd_sym_from_r_symndx (&htab->sym_cache, | |
3084 | - abfd, r_symndx); | |
3085 | - | |
3086 | - symtype = ELF_ST_TYPE (isym->st_info); | |
3087 | - | |
3088 | - /* STT_GNU_IFUNC must keep GOTPCREL relocations and skip | |
3089 | - relocation against undefined symbols. */ | |
3090 | - if (symtype == STT_GNU_IFUNC || isym->st_shndx == SHN_UNDEF) | |
3091 | - continue; | |
3092 | - | |
3093 | - if (isym->st_shndx == SHN_ABS) | |
3094 | - tsec = bfd_abs_section_ptr; | |
3095 | - else if (isym->st_shndx == SHN_COMMON) | |
3096 | - tsec = bfd_com_section_ptr; | |
3097 | - else if (isym->st_shndx == SHN_X86_64_LCOMMON) | |
3098 | - tsec = &_bfd_elf_large_com_section; | |
3099 | - else | |
3100 | - tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); | |
3101 | - | |
3102 | - h = NULL; | |
3103 | - toff = isym->st_value; | |
3104 | - } | |
3405 | + h = elf_x86_64_get_local_sym_hash (htab, sec->owner, | |
3406 | + (const Elf_Internal_Rela *) irel, | |
3407 | + FALSE); | |
3105 | 3408 | else |
3106 | 3409 | { |
3107 | - indx = r_symndx - symtab_hdr->sh_info; | |
3108 | - h = elf_sym_hashes (abfd)[indx]; | |
3109 | - BFD_ASSERT (h != NULL); | |
3110 | - | |
3410 | + h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info]; | |
3111 | 3411 | while (h->root.type == bfd_link_hash_indirect |
3112 | 3412 | || h->root.type == bfd_link_hash_warning) |
3113 | 3413 | h = (struct elf_link_hash_entry *) h->root.u.i.link; |
3114 | - | |
3115 | - /* STT_GNU_IFUNC must keep GOTPCREL relocations. We also | |
3116 | - avoid optimizing GOTPCREL relocations againt _DYNAMIC | |
3117 | - since ld.so may use its link-time address. */ | |
3118 | - if (h->type == STT_GNU_IFUNC) | |
3119 | - continue; | |
3120 | - | |
3121 | - /* Undefined weak symbol is only bound locally in executable | |
3122 | - and its reference is resolved as 0 without relocation | |
3123 | - overflow. We can only perform this optimization for | |
3124 | - GOTPCRELX relocations since we need to modify REX byte. | |
3125 | - It is OK convert mov with R_X86_64_GOTPCREL to | |
3126 | - R_X86_64_PC32. */ | |
3127 | - if ((relocx || opcode == 0x8b) | |
3128 | - && UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, | |
3129 | - TRUE, | |
3130 | - elf_x86_64_hash_entry (h))) | |
3131 | - { | |
3132 | - if (opcode == 0xff) | |
3133 | - { | |
3134 | - /* Skip for branch instructions since R_X86_64_PC32 | |
3135 | - may overflow. */ | |
3136 | - if (require_reloc_pc32) | |
3137 | - continue; | |
3138 | - } | |
3139 | - else if (relocx) | |
3140 | - { | |
3141 | - /* For non-branch instructions, we can convert to | |
3142 | - R_X86_64_32/R_X86_64_32S since we know if there | |
3143 | - is a REX byte. */ | |
3144 | - to_reloc_pc32 = FALSE; | |
3145 | - } | |
3146 | - | |
3147 | - /* Since we don't know the current PC when PIC is true, | |
3148 | - we can't convert to R_X86_64_PC32. */ | |
3149 | - if (to_reloc_pc32 && is_pic) | |
3150 | - continue; | |
3151 | - | |
3152 | - goto convert; | |
3153 | - } | |
3154 | - else if ((h->def_regular | |
3155 | - || h->root.type == bfd_link_hash_defined | |
3156 | - || h->root.type == bfd_link_hash_defweak) | |
3157 | - && h != htab->elf.hdynamic | |
3158 | - && SYMBOL_REFERENCES_LOCAL (link_info, h)) | |
3159 | - { | |
3160 | - /* bfd_link_hash_new or bfd_link_hash_undefined is | |
3161 | - set by an assignment in a linker script in | |
3162 | - bfd_elf_record_link_assignment. */ | |
3163 | - if (h->def_regular | |
3164 | - && (h->root.type == bfd_link_hash_new | |
3165 | - || h->root.type == bfd_link_hash_undefined)) | |
3166 | - { | |
3167 | - /* Skip since R_X86_64_32/R_X86_64_32S may overflow. */ | |
3168 | - if (require_reloc_pc32) | |
3169 | - continue; | |
3170 | - goto convert; | |
3171 | - } | |
3172 | - tsec = h->root.u.def.section; | |
3173 | - toff = h->root.u.def.value; | |
3174 | - symtype = h->type; | |
3175 | - } | |
3176 | - else | |
3177 | - continue; | |
3178 | - } | |
3179 | - | |
3180 | - /* We can only estimate relocation overflow for R_X86_64_PC32. */ | |
3181 | - if (!to_reloc_pc32) | |
3182 | - goto convert; | |
3183 | - | |
3184 | - if (tsec->sec_info_type == SEC_INFO_TYPE_MERGE) | |
3185 | - { | |
3186 | - /* At this stage in linking, no SEC_MERGE symbol has been | |
3187 | - adjusted, so all references to such symbols need to be | |
3188 | - passed through _bfd_merged_section_offset. (Later, in | |
3189 | - relocate_section, all SEC_MERGE symbols *except* for | |
3190 | - section symbols have been adjusted.) | |
3191 | - | |
3192 | - gas may reduce relocations against symbols in SEC_MERGE | |
3193 | - sections to a relocation against the section symbol when | |
3194 | - the original addend was zero. When the reloc is against | |
3195 | - a section symbol we should include the addend in the | |
3196 | - offset passed to _bfd_merged_section_offset, since the | |
3197 | - location of interest is the original symbol. On the | |
3198 | - other hand, an access to "sym+addend" where "sym" is not | |
3199 | - a section symbol should not include the addend; Such an | |
3200 | - access is presumed to be an offset from "sym"; The | |
3201 | - location of interest is just "sym". */ | |
3202 | - if (symtype == STT_SECTION) | |
3203 | - toff += raddend; | |
3204 | - | |
3205 | - toff = _bfd_merged_section_offset (abfd, &tsec, | |
3206 | - elf_section_data (tsec)->sec_info, | |
3207 | - toff); | |
3208 | - | |
3209 | - if (symtype != STT_SECTION) | |
3210 | - toff += raddend; | |
3211 | 3414 | } |
3212 | - else | |
3213 | - toff += raddend; | |
3214 | 3415 | |
3215 | - /* Don't convert if R_X86_64_PC32 relocation overflows. */ | |
3216 | - if (tsec->output_section == sec->output_section) | |
3217 | - { | |
3218 | - if ((toff - roff + 0x80000000) > 0xffffffff) | |
3219 | - continue; | |
3220 | - } | |
3221 | - else | |
3222 | - { | |
3223 | - bfd_signed_vma distance; | |
3224 | - | |
3225 | - /* At this point, we don't know the load addresses of TSEC | |
3226 | - section nor SEC section. We estimate the distrance between | |
3227 | - SEC and TSEC. We store the estimated distances in the | |
3228 | - compressed_size field of the output section, which is only | |
3229 | - used to decompress the compressed input section. */ | |
3230 | - if (sec->output_section->compressed_size == 0) | |
3231 | - { | |
3232 | - asection *asect; | |
3233 | - bfd_size_type size = 0; | |
3234 | - for (asect = link_info->output_bfd->sections; | |
3235 | - asect != NULL; | |
3236 | - asect = asect->next) | |
3237 | - /* Skip debug sections since compressed_size is used to | |
3238 | - compress debug sections. */ | |
3239 | - if ((asect->flags & SEC_DEBUGGING) == 0) | |
3240 | - { | |
3241 | - asection *i; | |
3242 | - for (i = asect->map_head.s; | |
3243 | - i != NULL; | |
3244 | - i = i->map_head.s) | |
3245 | - { | |
3246 | - size = align_power (size, i->alignment_power); | |
3247 | - size += i->size; | |
3248 | - } | |
3249 | - asect->compressed_size = size; | |
3250 | - } | |
3251 | - } | |
3252 | - | |
3253 | - /* Don't convert GOTPCREL relocations if TSEC isn't placed | |
3254 | - after SEC. */ | |
3255 | - distance = (tsec->output_section->compressed_size | |
3256 | - - sec->output_section->compressed_size); | |
3257 | - if (distance < 0) | |
3258 | - continue; | |
3416 | + /* STT_GNU_IFUNC must keep GOTPCREL relocations. */ | |
3417 | + if (h != NULL && h->type == STT_GNU_IFUNC) | |
3418 | + continue; | |
3259 | 3419 | |
3260 | - /* Take PT_GNU_RELRO segment into account by adding | |
3261 | - maxpagesize. */ | |
3262 | - if ((toff + distance + maxpagesize - roff + 0x80000000) | |
3263 | - > 0xffffffff) | |
3264 | - continue; | |
3265 | - } | |
3420 | + converted = FALSE; | |
3421 | + if (!elf_x86_64_convert_load_reloc (abfd, sec, contents, irel, h, | |
3422 | + &converted, link_info)) | |
3423 | + goto error_return; | |
3266 | 3424 | |
3267 | -convert: | |
3268 | - if (opcode == 0xff) | |
3425 | + if (converted) | |
3269 | 3426 | { |
3270 | - /* We have "call/jmp *foo@GOTPCREL(%rip)". */ | |
3271 | - unsigned int nop; | |
3272 | - unsigned int disp; | |
3273 | - bfd_vma nop_offset; | |
3274 | - | |
3275 | - /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to | |
3276 | - R_X86_64_PC32. */ | |
3277 | - modrm = bfd_get_8 (abfd, contents + roff - 1); | |
3278 | - if (modrm == 0x25) | |
3427 | + changed = converted; | |
3428 | + if (h) | |
3279 | 3429 | { |
3280 | - /* Convert to "jmp foo nop". */ | |
3281 | - modrm = 0xe9; | |
3282 | - nop = NOP_OPCODE; | |
3283 | - nop_offset = irel->r_offset + 3; | |
3284 | - disp = bfd_get_32 (abfd, contents + irel->r_offset); | |
3285 | - irel->r_offset -= 1; | |
3286 | - bfd_put_32 (abfd, disp, contents + irel->r_offset); | |
3430 | + if (h->got.refcount > 0) | |
3431 | + h->got.refcount -= 1; | |
3287 | 3432 | } |
3288 | 3433 | else |
3289 | 3434 | { |
3290 | - /* Convert to "nop call foo". ADDR_PREFIX_OPCODE | |
3291 | - is a nop prefix. */ | |
3292 | - modrm = 0xe8; | |
3293 | - nop = link_info->call_nop_byte; | |
3294 | - if (link_info->call_nop_as_suffix) | |
3295 | - { | |
3296 | - nop_offset = irel->r_offset + 3; | |
3297 | - disp = bfd_get_32 (abfd, contents + irel->r_offset); | |
3298 | - irel->r_offset -= 1; | |
3299 | - bfd_put_32 (abfd, disp, contents + irel->r_offset); | |
3300 | - } | |
3301 | - else | |
3302 | - nop_offset = irel->r_offset - 2; | |
3435 | + if (local_got_refcounts != NULL | |
3436 | + && local_got_refcounts[r_symndx] > 0) | |
3437 | + local_got_refcounts[r_symndx] -= 1; | |
3303 | 3438 | } |
3304 | - bfd_put_8 (abfd, nop, contents + nop_offset); | |
3305 | - bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1); | |
3306 | - r_type = R_X86_64_PC32; | |
3307 | - } | |
3308 | - else | |
3309 | - { | |
3310 | - unsigned int rex; | |
3311 | - unsigned int rex_mask = REX_R; | |
3312 | - | |
3313 | - if (r_type == R_X86_64_REX_GOTPCRELX) | |
3314 | - rex = bfd_get_8 (abfd, contents + roff - 3); | |
3315 | - else | |
3316 | - rex = 0; | |
3317 | - | |
3318 | - if (opcode == 0x8b) | |
3319 | - { | |
3320 | - if (to_reloc_pc32) | |
3321 | - { | |
3322 | - /* Convert "mov foo@GOTPCREL(%rip), %reg" to | |
3323 | - "lea foo(%rip), %reg". */ | |
3324 | - opcode = 0x8d; | |
3325 | - r_type = R_X86_64_PC32; | |
3326 | - } | |
3327 | - else | |
3328 | - { | |
3329 | - /* Convert "mov foo@GOTPCREL(%rip), %reg" to | |
3330 | - "mov $foo, %reg". */ | |
3331 | - opcode = 0xc7; | |
3332 | - modrm = bfd_get_8 (abfd, contents + roff - 1); | |
3333 | - modrm = 0xc0 | (modrm & 0x38) >> 3; | |
3334 | - if ((rex & REX_W) != 0 | |
3335 | - && ABI_64_P (link_info->output_bfd)) | |
3336 | - { | |
3337 | - /* Keep the REX_W bit in REX byte for LP64. */ | |
3338 | - r_type = R_X86_64_32S; | |
3339 | - goto rewrite_modrm_rex; | |
3340 | - } | |
3341 | - else | |
3342 | - { | |
3343 | - /* If the REX_W bit in REX byte isn't needed, | |
3344 | - use R_X86_64_32 and clear the W bit to avoid | |
3345 | - sign-extend imm32 to imm64. */ | |
3346 | - r_type = R_X86_64_32; | |
3347 | - /* Clear the W bit in REX byte. */ | |
3348 | - rex_mask |= REX_W; | |
3349 | - goto rewrite_modrm_rex; | |
3350 | - } | |
3351 | - } | |
3352 | - } | |
3353 | - else | |
3354 | - { | |
3355 | - /* R_X86_64_PC32 isn't supported. */ | |
3356 | - if (to_reloc_pc32) | |
3357 | - continue; | |
3358 | - | |
3359 | - modrm = bfd_get_8 (abfd, contents + roff - 1); | |
3360 | - if (opcode == 0x85) | |
3361 | - { | |
3362 | - /* Convert "test %reg, foo@GOTPCREL(%rip)" to | |
3363 | - "test $foo, %reg". */ | |
3364 | - modrm = 0xc0 | (modrm & 0x38) >> 3; | |
3365 | - opcode = 0xf7; | |
3366 | - } | |
3367 | - else | |
3368 | - { | |
3369 | - /* Convert "binop foo@GOTPCREL(%rip), %reg" to | |
3370 | - "binop $foo, %reg". */ | |
3371 | - modrm = 0xc0 | (modrm & 0x38) >> 3 | (opcode & 0x3c); | |
3372 | - opcode = 0x81; | |
3373 | - } | |
3374 | - | |
3375 | - /* Use R_X86_64_32 with 32-bit operand to avoid relocation | |
3376 | - overflow when sign-extending imm32 to imm64. */ | |
3377 | - r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32; | |
3378 | - | |
3379 | -rewrite_modrm_rex: | |
3380 | - bfd_put_8 (abfd, modrm, contents + roff - 1); | |
3381 | - | |
3382 | - if (rex) | |
3383 | - { | |
3384 | - /* Move the R bit to the B bit in REX byte. */ | |
3385 | - rex = (rex & ~rex_mask) | (rex & REX_R) >> 2; | |
3386 | - bfd_put_8 (abfd, rex, contents + roff - 3); | |
3387 | - } | |
3388 | - | |
3389 | - /* No addend for R_X86_64_32/R_X86_64_32S relocations. */ | |
3390 | - irel->r_addend = 0; | |
3391 | - } | |
3392 | - | |
3393 | - bfd_put_8 (abfd, opcode, contents + roff - 2); | |
3394 | - } | |
3395 | - | |
3396 | - irel->r_info = htab->r_info (r_symndx, r_type); | |
3397 | - changed_contents = TRUE; | |
3398 | - changed_relocs = TRUE; | |
3399 | - | |
3400 | - if (h) | |
3401 | - { | |
3402 | - if (h->got.refcount > 0) | |
3403 | - h->got.refcount -= 1; | |
3404 | - } | |
3405 | - else | |
3406 | - { | |
3407 | - if (local_got_refcounts != NULL | |
3408 | - && local_got_refcounts[r_symndx] > 0) | |
3409 | - local_got_refcounts[r_symndx] -= 1; | |
3410 | 3439 | } |
3411 | 3440 | } |
3412 | 3441 | |
3413 | 3442 | if (contents != NULL |
3414 | 3443 | && elf_section_data (sec)->this_hdr.contents != contents) |
3415 | 3444 | { |
3416 | - if (!changed_contents && !link_info->keep_memory) | |
3445 | + if (!changed && !link_info->keep_memory) | |
3417 | 3446 | free (contents); |
3418 | 3447 | else |
3419 | 3448 | { |
@@ -3424,7 +3453,7 @@ rewrite_modrm_rex: | ||
3424 | 3453 | |
3425 | 3454 | if (elf_section_data (sec)->relocs != internal_relocs) |
3426 | 3455 | { |
3427 | - if (!changed_relocs) | |
3456 | + if (!changed) | |
3428 | 3457 | free (internal_relocs); |
3429 | 3458 | else |
3430 | 3459 | elf_section_data (sec)->relocs = internal_relocs; |